본문 바로가기

방법론 공부/계량통계 방법론

[STATA] 정말 유용한 egen row: mean, sum, total, max, min, tag, group, concat, cut

egen command를 통해 활용할 수 있는 함수들을 몇 가지 알아보겠습니다. 




mean()

egen mean_price = mean(price), by(store_id)


이는 각각의 store_id에 대하여 price의 평균값을 mean_price라는 새로운 변수로 저장합니다. 예컨대 각각의 store 물건 가격의 평균값이라고 할 수 있지요.

이때, 관측치에 결측값이 있으면 mean을 구하지 못합니다. 


rowmean()

. egen avg = rowmean(a_score b_score c_score) 


이는 각각의 관측값에서 서로 다른 변수 a_score,b_score,c_score 간의 평균값을 계산해서 새로운 변수로 저장합니다. 예컨대 a,b,c가 수학, 과학, 영어 점수일 때, 전과목의 평균치를 구할 수 있습니다. 

그냥 반전체 과목 평균을 구하고 싶으면 mean ()을 쓰는게 적잘하겠죠. 

이때 관측치에 결측값이 있으면 rowmean()은 결측값을 제외한 나머지 값들의 평균을 구합니다. 모든 변수에 대해 값이 결측되었을 때에만 결측값을 제시합니다.


한편, 변수가 너무 많을 때는 다음과 같은 command를 쓰면 유용합니다. 이렇게 command를 설정해두면 나중에 dataset에 사회 점수를 추가한다거나 할 때에도 command를 재입력하지 않아도 됩니다. 


egen mean_score = rowmean(*_score)


다음의 그림은 두 function의 차이를 한눈에 설명해줍니다.




sum()  & rowtotal() 

     +   rownonmiss()

egen team_effort = sum(effort), by(team)
egen total_answers = rowtotal(question_*)


rowtotal의 경우, 결측값을 0으로 처리하여 결과값을 냅니다. 따라서 모든 변수에 대해 관측치가 0이었을 때, rowmean이 값을 제시하지 못했던 것에 비해 이때는 0이라는 결과가 나옵니다. 이때 rowtotal의 결과 역시 결측값으로 제시하고 싶다면 다음과 같은 command를 써야 합니다.

egen total_answers = rowtotal(question_*)
egen nonmissing_answers = rownonmiss(question_*) // (1)
replace total_answers = . if nonmissing_answers == 0 // (2)
drop nonmissing_answers


(1)은 각 표본이 몇 개의 변수에 대해 관측치가 있는지, 즉, 결측값이 있는지 여부를 제시해줍니다. 

그리고 (2)를 통해 모든 변수에 대해 관측값이 없는 표본에 대해 total_answer를 결측값으로 처리합니다. 
마지막으로 단순히 이 처리를 위해 만들어졌던 nonmissing_answers 변수를 drop하면 되지요.



total()


() 안에 있는 조건에 따라 count()한 것 과 같은 결과를 산출합니다. () 안의 조건에 맞다면 1, 아니면 0으로 계산하여 이를 합산합니다. 다음의 예시는 각각의 가족에 17세 이상의 아동이 몇 명이나 있는가를 계산하는 command입니다.


egen nchild = total(age <= 17), by(family) 


각각의 아동이 표본일 때, 본인을 제외한 아동이 몇 명이나 있는지를 알아보는 것이라면 다음의 command를 추가하면 됩니다.


replace nchild=nchild-(age<=17)


다음과 같이 하나 이상의 조건을 붙일 수도 있습니다. 


 . egen nsisters = total(age <= 17 & sex == 1), by(family)

 . replace nsisters = nsisters - (age <= 17 & sex == 1) 



max() & rowmax(), min() & rowmin()

     + count ()

이는 나중에 변수들의 값들을 [0,1] 사이의 값으로 normalize할 때 유용합니다. 각 회사에서 가장 임금 수준이 높으면 1, 그리고 가장 낮으면 0을 부여하고 싶다고 합시다. 

egen max_wage_f=max(wage), by(firm)
egen min_wage_f=min(wage), by(firm)

gen norm_wage_f=(wage-min_wage_f)/(max_wage_f-min_wage_f) // (1)

replace norm_wage_f = 0.5 if norm_wage_f == . // (2)


(1)을 통해 각각의 wage값의 전체 관측값에서의 상대적 위치를 계산하고[0,1], 

(2)를 통해 전 사원의 임금 수준이 동일한 회사들에 대해(max-min=0) 0.5의 값을 부여합니다. 




또다른 예로, 학교에서의 학생들에 대한 dataset이 있을 때, 아버지가 고등학교를 중퇴한 학생들의 수를 regress에 넣고싶다고 합시다. 


egen f_dropout_kids_only = count(student_id) if f_educ<12, by(school) // (1)
egen f_dropout_kids = max(f_dropout_kids_only), by(school) // (2)
drop f_dropout_kids_only // (3) 


(1)을 통해 해당하는 학생들의 숫자를 세고, (2)를 통해 이렇게 구해진 값에 해당하는 변수를 만듭니다. 이때 단순히 "egen f_dropout_kids = f_dropout_kids_only"를 하지 않는 이유는 f_educ>=일 경우, f_dropout_kids_only의 값이 결측값이 되기 때문입니다. 

마지막으로 (3)을 통해 (2)를 구하기 위해 사용한 변수를 drop합니다. 


이때 count() command는 결측값을 제외하고 실제 값이 존재하는 표본의 수를 셉니다. by option과 함께 유용하게 사용됩니다. 



기타 egen command를 통해 유용하게 사용할 수 있는 통계학적 계산들에는 sd() (표준편차), median(),mode() 등이 있습니다.  여러 변수들에 대해 이 값들을 계산하고 싶을 때에는 앞서와 마찬가지로 row : rowmean()rowmin()rowmax()rowsd()rowtotal() 등을 사용할 수 있습니다. 



tag()


휘발유 가격에 대한 dataset이 있다고 가정합시다. 각각의 표본은 연료의 종류, 갤론 당 가격, 주유소의 고유번호, 그리고 매주 기록된 휘발유 가격을 갖고 있습니다. 모든 주유소가 휘발유 가격을 매주 기록한 것은 아니고, 몇몇 주유소의 휘발유 가격에는 결측값이 있습니다. 총 50주 동안 이처럼 휘발유 가격을 기록했다 할 때, 매주 가격을 기록한 주유소의 data만을 사용하고 싶습니다. 


이때 단순히 


egen station_count = count(week), by(station) 


라는 명령어를 사용하면 각각의 주유소에 대해 몇 개의 표본이 있는지를 셀 수 있기는 하지만, 각각의 표본에 대해 변수가 week만 있는 것이 아니라 다양하기 때문에 우리가 원하는 값을 얻을 수 없습니다. dataset이 다음과 같이 정렬되어 있는 상황을 생각해봅시다.


week station fuel_type price ... 

 1       1    leaded    35

 1        1    unleaded  25


두 측정값은 같은 주유소에서 한 주에 측정된 값들이지만 앞서의 command를 사용하면 count(week)이 2로 계산될 것입니다. 따라서 station-week "조합"이 몇 개인지를 세야하는데, 이때 tag command를 사용할 수있습니다. 이를 통해 각각의 station-week "조합" 중 하나의 표본에 대해서만 1을 부여하고 나머지에는 0을 부여한 뒤, 이를 모두 합하여 총 조합의 수를 계산할 수 있습니다. 이때 count가 아니라 sum을 사용합니다.


egen station_week_tag = tag(station week) 
egen weeks_of_station = sum(station_week_tag), by(station)




group()


group() 역시 tag()와 비슷하게 사용되지만, tag()가 새로운 조합에만 1을 부여하고 나머지에는 0을 부여했던 것과 달리, group()은 첫번째 조합에 해당하는 모든 표본에 1을, 두번째 조합에 2를, 세번째 조합에 3을 ... 부여합니다. 이를 통해 모든 조합을 열거하는 하나의 변수를 만들 수 있습니다. 


egen sexmar=group(sex marital), label


는 sex와 marital 변수에서의 값이 동일한 "조합"에 group이라는 변수를 생성하여 각각 숫자를 부여합니다. label option에 따라 sex와 marital 변수에 대한 설명을 추가할 수 있습니다. 



concat()


concat() command는 두 개 이상의 변수를 하나의 변수로 만들고 싶을 때 사용합니다. 그리고 두 변수명을 새로운 변수에 어떻게 표시할 것인지를 설정할 수 있습니다. 


egen sexmarcon=concat(sex marital), p(/)


는 sex/marital, 예컨대 male/married를 값으로 하는 변수 sexmarcon을 생성합니다. 



cut()


cut() function은 여러 값을 범주화하여 나눌 때 유용합니다. 예컨대 사람들의 나이를 이 변수를 사용하여 카테고리화한다고 합시다. 


 egen age_cat1 = cut(age), at(18, 25, 35, 45, 55, 65, 75, 90)


의 command를 사용하면 18세 미만의 관측치는 결측값이 부여되고, 90세 이상의 관측치는 모두 90이라는 숫자가 부여됩니다. 즉, 새로 만들어질 각 카테고리에서의 최소값을 at()에서 지정해주면 됩니다. 혹은 다음과 같이 새로 만들어질 group의 수를 직접 지정해줄 수도 있습니다. 


egen age_cat2 = cut(age), group(6)





egen과 관련하여 다음의 블로그에 정리가 매우 잘 되어 있었기에 본 포스팅에서는 해당 부분을 번역 및 정리하고, 몇 가지를 추가했습니다.

출처: http://stataproject.blogspot.com/2007/12/step-4-thank-god-for-egen-command.html