R로 WTP 계산하기.

7 분 소요

Compute WTP by R

  • R을 사용해서, WTP를 계산하는 방법을 정리하였습니다.

What is R?

  • C, C++, python 등 세상에는 다양한 프로그래밍 언어들이 있습니다. 물론 요즘에는 모든 언어들이 ‘나도 다 할 수 있어!’라고 떠들기는 하지만, 각자 언어별로 강점과 약점은 꽤 뚜렷합니다. (참고로 저는 python을 주 언어로 사용하고 있습니다)

  • R은 (General, multi-paradigm) 프로그래밍 언어로, 역시, ‘다 잘한다’라고 하지만, 일반 소프트웨어 개발 쪽에서는 거의 쓰이지 않고, 통계 분야에서 아주 강력한 힘을 가지고 있습니다. 특히 본 분석에서 사용하는 logit model과 같은 것들은 python에는 없고 R에만 존재합니다. 그외로도, 많은 통계 관련 패키지들이 R에 많이 존재하죠.

  • R은 다른 프로그래밍 언어와 비교하는 것보다는 SPSS, SAS, Stata등 통계 패키지들과 유사점을 가지고 있다고 보는 것이 타당합니다. R이 영향을 받은 언어 또한 통계 계산 언어(statistical computing language)였던 S였고, 현재 R을 주로 사용하고 있는 사람들도 수학자/통계학자 쪽에 많이 분포되어 있죠. 그리고, 공짜입니다(물론 회사에서 쓸 경우에는 돈을 지불해야 하는 라이센스들도 아마 있기는 할 거에요.

  • 아무튼, 한 줄로. “통계의 다양한 기법들을 다른 언어들보다 많이 지원하는, 데이터 분석 언어” 라고 일단은 생각하시면 됩니다.

R versus python

  • R도 python도 모두 인기가 많지만, 사실 두 언어는 좀 뚜렷한 차이점이 있습니다. python의 경우 몇 가지 문법 등에서 ‘프로그래밍 언어’에서 공통으로 활용되는 문법(ex. assignment)을 따르지만, R은 그렇지 않은 경우들이 좀 있어요. 사실, 설명하기는 조금 어려운데, 제가 느끼기에는 python보다 r이 문턱이 조금 높은 편인 것 같습니다.

  • python의 경우 tensorflow, pytorch와 같은 ‘머신러닝용 패키지’에 특화되어 있는 반면, R의 경우 오늘 소개할 gmnl과 같이 통계쪽에서 사용되는 패키지들이 탄탄하게 존재합니다. 네. 그렇습니다. 살아남으려면 다 잘해야합니다 호호호호.

install R, RStudio

  • 아무튼, R을 깔아봅시다. 그리고, 거의 공식 IDE인, Rstudio도 함께 설치합니다.
  • IDE는 Integrated Development Editor, ‘통합 개발 편집기’를 의미합니다. 그냥 뭐, 워드 같은 거죠. 아무튼, 이걸 설치하지 않으면, 다음과 같은 화면에서 프로그래밍을 해야 합니다 하하하.

case study: Electricity

  • 아무튼, 뭐 케이스 스터디를 해봐야 될텐데, 사실 현재 우리는 데이터가 확보되지 않은 상황이죠.
  • 고맙게도, R의 패키지 중 하나인 mlogit에는 이미 분석을 위한 데이터가 존재합니다.
  • 우리는 그 중에서 사람들의 전기 사용료 산정 방식의 선호를 알아보기 위해 Choice-based의 방식으로 수행된 설문조사 데이터를 활용하여, logit model을 구축하고, WTP를 계산해보겠습니다.
  • (해당 데이터는 https://rdrr.io/rforge/mlogit/man/Electricity.html에서 가져왔습니다).

  • 데이터에 대한 설명:
    • choice: the choice of the individual, one of 1, 2, 3, 4. 선택되면 True 아니면 False
    • id: the individual index, 설문자를 구별하기 위한 변수
    • pfi: fixed price at a stated cents per kWh, 가격.
    • cli: the length of contract that the supplier offered, in years (such as 1 year or 5 years.)
    • loci: is the supplier a local company,
    • wki: is the supplier a well-known company, todi: a time-of-day rate under which the price is 11 cents per kWh from 8am to 8pm and 5 cents per kWh from 8pm to 8am. seasi: a seasonal rate under which the price is 10 cents per kWh in the summer, 8 cents per kWh in the winter, and 6 cents per kWh in the spring and fall. Like TOD rates, these prices did not vary.

Required packages

  • Discrete-choice model을 구축하고, WTP를 계산하기 위해서 우리는 다음의 두 가지 패키지가 필요합니다. 두 방법에 미묘한 차이가 있는 것 같기는 한데, gmnl은 2017년에 나왔고, mlogit은 2009년에 나왔으므로 최신식을 쓰기로 합니다. 그리고, mlogit에서는 WTP를 바로 계산해주지 않으므로(물론 coefficient를 그냥 나누면 되는 것이기는 하지만), gmnl을 쓰기로 합니다.

  • mlogit: Multinomial Logit Models
    • Maximum Likelihood estimation of random utility discrete choice models, as described in Kenneth Train (2009) Discrete Choice Methods with Simulations
  • gmnl: Multinomial Logit Models with Random Parameters
    • An implementation of maximum simulated likelihood method for the estimation of multinomial logit models with random coefficients.
    • Specifically, it allows estimating models with continuous heterogeneity such as the mixed multinomial logit and the generalized multinomial logit.
    • It also allows estimating models with discrete heterogeneity such as the latent class and the mixed-mixed multinomial logit model.

install and use library

install.packages(mlogit)
install.packages(gmnl)
library(mlogit)
library(gmnl)
  • python과 R과 같은 최근의 언어들의 강점은 ‘다른 사람이 이미 만들어준 좋은 코드를 쉽게 가져와서 마치 내 것처럼 쓸 수 있다는 것이죠’. 간단하게 두 명령어를 각각 치면 됩니다.

install.packages(“mlogit”)

  • mlogit라는 이름의 라이브러리를 설치하겠다.

library(mlogit)

  • mlogit를 사용하겠다는 이야기죠.

  • 그러니까, 만약 어떤 라이브러리가 필요하면 그 라이브러리를 이 두 명령어만으로 설치하고 사용할 수 있습니다. 자, 이제 mlogit, gmnl에 있는 함수와 객체들을 내 것처럼 사용할 수 있습니다.

read and manipulate data.frame ==> mlogit.data

data("Electricity”, package = 'mlogit')
Electr <- mlogit.data(Electricity, id.var = 'id', choice = 'choice',
                     varying = 3:26, shape = 'wide', sep = "")
write.csv(Electr, 'electr_df.csv')
electr <- read.csv('electr_df.csv')
electr_mlogit_data <- mlogit.data(data=electr, id.var='id', choice='choice', alt.var='alt')
  • 데이터는 2가지 방법이 있는데, 우리는 케이스 스터디 중이므로, mlogit으로부터 데이터를 가져오거나, 같은 형태의 데이터를 csv로 읽을 수 가 있습니다. 아래의 형식은 mlogit의 Electricity를 읽고, 해당 데이터를 우리가 원하는 형태의 테이블로 변경하는 것을 말합니다. 하지만, 이 부분은 해석이 어렵고, 조금 복잡해 보여서, 저는 해당 데이터, Electr에 저장되어 있는 결과를 가져와서 따로 csv로 저장해두었습니다. 그래야, 추후에 제가 어떤 데이터를 만들어야 할지 감이 오니까요.
electr <- read.csv("electr_df.csv")
  • ‘electr_df.csv’파일을 읽어서, electr라는 변수에 저장합니다.
  • 이 때, electr의 데이터 타입은 data.frame, 일종의 테이블 형태입니다.
electr_mlogit_data <- mlogit.data(data=electr, id.var='id', choice='choice', alt.var='alt')
  • 이후 gmnl에 데이터를 전달하기 위해서는 즉 data.frame에서 mlogit.data의 데이터 타입으로 변경되는 것이 필요합니다.따라서, 본 단계에서는 mlogit.data의 형태로 데이터의 형태를 변경해주고, 필요한 각각의 특성을 전달합니다.
    • data ⇒ input data.frame
    • id.var ⇒ the name of the variable that contains the individual index
    • choice ⇒ the variable indicating the choice made
    • alt.var ⇒ the name of the variable that contains the alternative index
  • 사실 “몇 가지 변수는 왜 필요할까?”싶지만 그냥 하라니까 하기로 합니다.

model fitting.

mlogit <- gmnl(formula=choice ~ pf + cl + loc + wk + tod + seas| 0, data = electr_mlogit_data, model='mnl')
  • gmnl에 데이터를 넘깁니다. 넘길 때, 다음의 attribute들도 함께 넘기게 되는데요.
    • formula: 어떤 형태의 방정식으로 모델링 할 것인가, 를 의미합니다. 이건 뒤에 다시 설명할게요.
    • data: 어떤 데이터를 사용할 것인지 의미하죠. 여기서는 앞서 만들어놓은 mlogit.data의 형태만 들어올 수 있습니다.
    • model: multinomial-logit-model, mixed-logit-model 등 다양한 모델을 사용할 수 있습니다. ‘mnl’의 경우 multinomial-logit-model을 의미합니다.
    • 이렇게 하고 나면 약간의 시간이 소요되고, 학습이 종료됩니다. 즉, multinomial-logit-model을 사용해서 우리가 준 formula에 맞춰서 electr_mlogit_data를 사용해서 학습을 끝냈다는 말이죠.

model fitting with formula.

mlogit <- gmnl(formula=choice ~ pf + cl + loc + wk + tod + seas| 0, data = electr_mlogit_data, model='mnl')
formula = choice ~ pf + cl + loc + wk + tod + seas| 0
  • 여기서 formula 부분만 집중해서 보겠습니다. 잘 모르겠지만, 잘 보면, 뭔가 1차 방정식 처럼 보이지 않나요? 이게 R에서 많이 쓰는 formula라는 것인데, y ~ x1 + x2 의 형태로 넘기는 것을 말합니다. 즉, x1, x2가 y에 영향을 미친다고 모델을 만드는 것이죠.

formula = choice ~ pf + cl | 0

  • 즉, formula를 이렇게 해서 넘기면, pf, cl만 고려하여 방정식이 세워집니다. 물론, 실제로는 다음과 같이 더 복잡한 모델을 넘길 수도 있지만, 실제로 이렇게까지 쓰는 경우는 많지 않은 것 같습니다. 더욱이, 우리는 그만큼 변수가 많은 상황도 아니니까요. 비교적 간단한 모형만으로도 괜찮을 것 같습니다.

  • The formula is divided in five parts, each of them separated by the symbol .
    • The first part is reserved for alternative-specific variables with a generic coefficient.
    • The second part corresponds to individual-specific variables with an alternative specific coefficients.
    • The third part corresponds to alternative-specific variables with an alternative-specific coefficident.
    • The fourth part is reserved for time-invariant variables that modify the mean of the random parameters.
    • Finally, the fifth part is reserved for time-invariant variables that enter in the scale coefficient or in the probability assignment in models with latent classes.

Check Coefficients.

getSummary.gmnl(mlogit)
            est          se      stat p         lwr        upr
pf   -0.6252278 0.023222316 -26.92357 0 -0.57971286 -0.6707427
cl   -0.1082991 0.008244215 -13.13637 0 -0.09214073 -0.1244575
loc   1.4422429 0.050557125  28.52700 0  1.54133301  1.3431527
wk    0.9955040 0.044780076  22.23096 0  1.08327134  0.9077367
tod  -5.4627587 0.183712509 -29.73537 0 -5.10268875 -5.8228286
seas -5.8400308 0.186677897 -31.28400 0 -5.47414888 -6.2059128

getSummary.gmnl(mlogit)
  • 구축된 모델의 coefficient들을 알 수 있습니다. 뭐, 대충 어떤 값을 가지고, 얼마나 신뢰할 수 있는지 등에 대해서 나옵니다.

compute WTP

wtp.gmnl(mlogit, wrt='pf')
      Estimate Std. Error t-value  Pr(>|t|)    
cl    0.173215   0.013818  12.535 < 2.2e-16 ***
loc  -2.306748   0.101586 -22.707 < 2.2e-16 ***
wk   -1.592226   0.080447 -19.792 < 2.2e-16 ***
tod   8.737230   0.077294 113.039 < 2.2e-16 ***
seas  9.340645   0.093025 100.410 < 2.2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

wtp.gmnl(mlogit, wrt='pf')
  • 구축된 모델에 대해서 ‘pf’에 대한 WTP를 계산해줍니다.
  • wrt: ‘with respect to’의 약자로, 무엇에 대해서 WTP를 계산할 것인지를 말하죠.

all code

install.packages(mlogit)
install.packages(gmnl)
library(mlogit)
library(gmnl)
electr <- read.csv("electr_df.csv")
electr_mlogit_data <- mlogit.data(data=electr, id.var='id', choice='choice', alt.var='alt')
mlogit <- gmnl(formula=choice ~ pf + cl + loc + wk + tod + seas| 0, data = electr_mlogit_data, model='mnl')
getSummary.gmnl(mlogit)
wtp.gmnl(mlogit, wrt='pf')

wrap-up

  • 아무튼, 오늘은 다음과 같은 내용을 정리했습니다.
    • 경제학/사회과학 분야에서 구축하는 고객들의 ‘선택 모형(Discrete-Choice Model)’은 머신러닝 분야에서 말하는classification 문제와 기법 적으로는 큰 차이가 없다. 그러나, 설명력과 노이즈 컨트롤 등의 목적으로 인해 discrete-choice model에서는 logistic regression을 기본으로 하는 모델을 사용한다.
    • python이 머신러닝 관련 패키지를 많이 지원하는 반면, R의 경우 통계 쪽 패키지를 다양하게 지원한다.
    • 데이터 분석 파이프라인에서 보면 가장 많은 시간이 들어가는 것은 데이터 전처리다. 그러나, 이 부분은 아주 많은 케이스들이 있으며 이를 자료로서 정리하는 것은 매우 어렵다. 오히려 이 부분은 이후 미팅때 질의응답 으로 논의하는 것이 좋을 것 같다. 그리고, 이건 그냥 엑셀로 하는 것이 더 쉬울 때도 있다.
    • 본 자료에서는 따라서, ‘데이터가 수집된 이후’ R을 사용하여 logit model을 구축하고, WTP를 계산하는 코드를 정리하였다. 데이터가 잘 정리되어 있다는 전제하에서, 해당 코드만 그대로 사용하면, 문제없이, WTP를 계산할 수 있을 것으로 예상된다.
  • 입니다. 쓰고나니, 별거 없네요. 하하. 사실 이걸 정리한다고 생각보다 많은 시간이 소비되었습니다 호호호.
  • 그리고, 개발자든 데이터 분석가든 코딩할 때 가장 많이 하는 것은 구글링입니다. 세상에는 이미 많은 실패의 경험들이 넘쳐나고, 그 경험은 구글에 몇번 뚝딱 치는 것만으로 획득할 수 있습니다. 뭔가 이상하다 싶으면 구글에 검색을 하면 좋습니다. 네 하하하하 아주 무책임한 조언입니다 호호호호

댓글남기기