기본 콘텐츠로 건너뛰기

데이터 가공 및 분석 - dplyr 패키지 (2)




 계속해서 dplyr 패키지를 이용한 데이터 가공에 대해서 이야기해 보겠습니다. subset과 다른 dplyr의 추가 기능 중 하나는 변수를 가공해서 새로운 변수를 만들 수 있다는 것입니다. 예를 들어 몸무게와 키를 이용해 체질량 지수 (BMI)를 계산하거나 혹은 달러 표시와 원화 표시를 동시에 할 수 있습니다. mutate 기능을 사용한 것으로 여기서는 1달러당 1100원으로 원화를 표시해 보겠습니다. mutate(price_kr=price*1100)%>%의 문법으로 앞에서 봤던 사용법과 크게 다르지 않습니다. 


D1%>%
  filter(cut=="Ideal")%>%  #Ideal 추출 
  select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
  mutate(price_kr=price*1100)%>% #원화표시 가격
  arrange(carat) #오름차순 정렬

> D1%>%
+   filter(cut=="Ideal")%>%  #Ideal 추출 
+   select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
+   mutate(price_kr=price*1100)%>% #원화표시 가격
+   arrange(carat) #오름차순 정렬
# A tibble: 18 x 6
   carat cut   color clarity price price_kr
          
 1  0.3  Ideal F     VS1       570   627000
 2  0.31 Ideal H     IF        772   849200
 3  0.31 Ideal D     VS2       942  1036200
 4  0.32 Ideal E     VVS1     1020  1122000
 5  0.33 Ideal G     IF        946  1040600
 6  0.33 Ideal H     VVS1      713   784300
 7  0.41 Ideal J     VS1       648   712800
 8  0.44 Ideal G     SI1       772   849200
 9  0.54 Ideal D     VS2      1993  2192300
10  0.6  Ideal F     VS1      2142  2356200
11  0.62 Ideal H     VS1      1808  1988800
12  0.7  Ideal F     SI1      2573  2830300
13  0.74 Ideal D     VS2      3858  4243800
14  1.01 Ideal D     SI2      5206  5726600
15  1.09 Ideal G     VVS2     8970  9867000
16  1.09 Ideal J     SI2      5034  5537400
17  1.11 Ideal F     VS2      9057  9962700
18  1.2  Ideal I     VS2      5699  6268900


 단순 계산 뿐 아니라 범주형 자료로 만들 수 있습니다. ifelse를 사용해 100만원을 기준으로 high와 low 그룹으로 나눠보겠습니다. mutate(price_group=ifelse(price_kr>1000000,"high","low"))%>%를 추가하면 됩니다. 

D1%>%
  filter(cut=="Ideal")%>%  #Ideal 추출 
  select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
  mutate(price_kr=price*1100)%>% #원화표시 가격
  mutate(price_group=ifelse(price_kr>1000000,"high","low"))%>% #가격분류
  arrange(carat) #오름차순 정렬

> D1%>%
+   filter(cut=="Ideal")%>%  #Ideal 추출 
+   select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
+   mutate(price_kr=price*1100)%>% #원화표시 가격
+   mutate(price_group=ifelse(price_kr>1000000,"high","low"))%>% #가격분류
+   arrange(carat) #오름차순 정렬
# A tibble: 18 x 7
   carat cut   color clarity price price_kr price_group
                 
 1  0.3  Ideal F     VS1       570   627000 low        
 2  0.31 Ideal H     IF        772   849200 low        
 3  0.31 Ideal D     VS2       942  1036200 high       
 4  0.32 Ideal E     VVS1     1020  1122000 high       
 5  0.33 Ideal G     IF        946  1040600 high       
 6  0.33 Ideal H     VVS1      713   784300 low        
 7  0.41 Ideal J     VS1       648   712800 low        
 8  0.44 Ideal G     SI1       772   849200 low        
 9  0.54 Ideal D     VS2      1993  2192300 high       
10  0.6  Ideal F     VS1      2142  2356200 high       
11  0.62 Ideal H     VS1      1808  1988800 high       
12  0.7  Ideal F     SI1      2573  2830300 high       
13  0.74 Ideal D     VS2      3858  4243800 high       
14  1.01 Ideal D     SI2      5206  5726600 high       
15  1.09 Ideal G     VVS2     8970  9867000 high       
16  1.09 Ideal J     SI2      5034  5537400 high       
17  1.11 Ideal F     VS2      9057  9962700 high       
18  1.2  Ideal I     VS2      5699  6268900 high       


 dplyr를 통해 데이터를 쉽게 추출하고 가공할 수 있다는 점은 큰 매력이라고 하겠습니다. 물론 이렇게 가공한 내용은 데이터프레임 이름<- csv="" nbsp="" span="">


 또 다른 중요한 기능은 그룹별 통계를 내서 새로운 데이터 프레임으로 만들 수 있는 기능입니다. group_by()와 summarise()를 통해 그룹별로 분류하고 평균이나 표준 편차 등 중요한 기본 통계량을 계산할 수 있습니다. 여기서는 cut 그룹별로 분류하고 가격을 알아보겠습니다. 


D1%>%
  select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
  group_by(cut)%>% #cut 그룹별 분류 
  summarise(cut_price=mean(price)) #그룹별 평균 가격 

> D1%>%
+   select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
+   group_by(cut)%>% #cut 그룹별 분류 
+   summarise(cut_price=mean(price)) #그룹별 평균 가격
# A tibble: 5 x 2
  cut       cut_price
           
1 Fair          3608 
2 Good          3850.
3 Very Good     4586 
4 Premium       6083.
5 Ideal         2929.

 의외로 프리미엄보다 아이디얼의 가격이 낮습니다. 아마도 캐럿 등 다른 요인이 있을 것 같은데 같이 표시해보겠습니다. summarise는 줄을 바꿔서 계속해서 명령을 추가할 수 있습니다. 

D1%>%
  select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
  group_by(cut)%>% #cut 그룹별 분류 
  summarise(cut_price=mean(price),
            cut_carat=mean(carat)) #그룹별 평균 가격 및 캐럿 

> D1%>%
+   select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
+   group_by(cut)%>% #cut 그룹별 분류 
+   summarise(cut_price=mean(price),
+             cut_carat=mean(carat)) #그룹별 평균 가격 및 캐럿
# A tibble: 5 x 3
  cut       cut_price cut_carat
                
1 Fair          3608      0.87 
2 Good          3850.     0.767
3 Very Good     4586      0.895
4 Premium       6083.     1.19 
5 Ideal         2929.     0.636


 역시 그런 결과가 나왔습니다. Ideal이 캐럿이 작습니다. 이에 여기에 각 값별로 숫자가 얼마나 되는지 알아보겠습니다. N=n()을 이용하면 됩니다. 


> D1%>%
+   select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
+   group_by(cut)%>% #cut 그룹별 분류 
+   summarise(cut_price=mean(price),
+             cut_carat=mean(carat),
+             N=n()) #그룹별 평균 비교
# A tibble: 5 x 4
  cut       cut_price cut_carat     N
                
1 Fair          3608      0.87      2
2 Good          3850.     0.767     9
3 Very Good     4586      0.895    11
4 Premium       6083.     1.19     10
5 Ideal         2929.     0.636    18


이렇게 얻은 통계 데이터를 D3라는 새로운 데이터 프레임으로 만들어보겠습니다. 


D3<-d1>%
  select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
  group_by(cut)%>% #cut 그룹별 분류 
  summarise(cut_price=mean(price),
            cut_carat=mean(carat),
            N=n()) #그룹별 평균 비교 

D3

> D3<-d1>%
+   select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
+   group_by(cut)%>% #cut 그룹별 분류 
+   summarise(cut_price=mean(price),
+             cut_carat=mean(carat),
+             N=n()) #그룹별 평균 비교 
> 
> D3
# A tibble: 5 x 4
  cut       cut_price cut_carat     N
                
1 Fair          3608      0.87      2
2 Good          3850.     0.767     9
3 Very Good     4586      0.895    11
4 Premium       6083.     1.19     10
5 Ideal         2929.     0.636    18


 앞서 소개한 aggregate 역시 데이터 분석에서 유용하게 쓰일 수 있지만, 이렇게 데이터 프레임으로 저장하기는 어렵습니다. dplyr의 유용성이 여기서 드러납니다. 


이제 마지막으로 diamonds 데이터 전체에 대해서도 비슷한 결과가 나오는지 알아보겠습니다. 표준편차까지 추가해서 알아보겠습니다. 

diamonds%>%
  select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
  group_by(cut)%>% #cut 그룹별 분류 
  summarise(cut_price=mean(price),
            cut_carat=mean(carat),
            N=n()) #그룹별 평균 비교 

> diamonds%>%
+   select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
+   group_by(cut)%>% #cut 그룹별 분류 
+   summarise(cut_price=mean(price),
+             cut_carat=mean(carat),
+             N=n()) #그룹별 평균 비교
# A tibble: 5 x 4
  cut       cut_price cut_carat     N
                
1 Fair          4359.     1.05   1610
2 Good          3929.     0.849  4906
3 Very Good     3982.     0.806 12082
4 Premium       4584.     0.892 13791
5 Ideal         3458.     0.703 21551


 전체 결과를 보니 표본이 전체 경향을 대표하기는 하지만 약간은 다르다는 점을 알 수 있습니다. 아무튼 각 그룹별 통계를 비롯한 여러 가지 데이터를 dplyr로 확인하고 저장할 수 있다는 점이 큰 매력이라고 할 수 있습니다. 다음에는 데이터 가공 및 정리에서 매우 중요한 데이터 합치기에 대해서 설명해 보겠습니다. 

댓글

이 블로그의 인기 게시물

몸에 철이 많으면 조기 사망 위험도가 높다?

 철분은 인체에 반드시 필요한 미량 원소입니다. 헤모글로빈에 필수적인 물질이기 때문에 철분 부족은 흔히 빈혈을 부르며 반대로 피를 자꾸 잃는 경우에는 철분 부족 현상이 발생합니다. 하지만 철분 수치가 높다는 것은 반드시 좋은 의미는 아닙니다. 모든 일에는 적당한 수준이 있게 마련이고 철 역시 너무 많으면 여러 가지 질병을 일으킬 수 있습니다. 철 대사에 문제가 생겨 철이 과다하게 축적되는 혈색소증 ( haemochromatosis ) 같은 드문 경우가 아니라도 과도한 철분 섭취나 수혈로 인한 철분 과잉은 건강에 문제를 일으킬 수 있습니다. 하지만 높은 철 농도가 수명에 미치는 영향에 대해서는 잘 알려지지 않았습니다.   하버드 대학의 이야스 다글라스( Iyas Daghlas )와 임페리얼 칼리지 런던의 데펜더 길 ( Dipender Gill )은 체내 철 함유량에 영향을 미치는 유전적 변이와 수명의 관계를 조사했습니다. 연구팀은 48972명의 유전 정보와 혈중 철분 농도, 그리고 기대 수명의 60/90%에서 생존 확률을 조사했습니다. 그 결과 유전자로 예측한 혈중 철분 농도가 증가할수록 오래 생존할 가능성이 낮은 것으로 나타났습니다. 이것이 유전자 자체 때문인지 아니면 높은 혈중/체내 철 농도 때문인지는 명확하지 않지만, 높은 혈중 철 농도가 꼭 좋은 뜻이 아니라는 것을 시사하는 결과입니다.   연구팀은 이 데이터를 근거로 건강한 사람이 영양제나 종합 비타민제를 통해 과도한 철분을 섭취할 이유는 없다고 주장했습니다. 어쩌면 높은 철 농도가 조기 사망 위험도를 높일지도 모르기 때문입니다. 그러나 임산부나 빈혈 환자 등 진짜 철분이 필요한 사람들까지 철분 섭취를 꺼릴 필요가 없다는 점도 강조했습니다. 연구 내용은 정상보다 높은 혈중 철농도가 오래 유지되는 경우를 가정한 것으로 본래 철분 부족이 있는 사람을 대상으로 한 것이 아니기 때문입니다. 낮은 철분 농도와 빈혈이 건강에 미치는 악영향은 이미 잘 알려져 있기 때문에 철...

렘 수면이 식이 패턴에 영향을 준다?

  ( Using a techniqu e called optogenetics, the activity of cells in the brain can be specifically suppressed with light pulses. Credit: Pascal Gugler / Insel Gruppe )  수면 중 빠른 안구 운동이 발생하는 렘 (REM) 수면은 아직도 그 기능이 완전히 밝혀지지 않았지만, 수면에서 매우 중요한 부분이라는 사실은 확실합니다. 렘 수면은 꿈과 관련이 깊으며 전체 수면 시간이 부족하지 않더라도 렘 수면 시간이 짧으면 다음날 집중력이 떨어지고 많이 피곤하게 됩니다. 아마도 렘 수면 시간 동안 여러 가지 기능과 작업이 이뤄짐을 시사하는 결과입니다.   베른 대학교 ( University of Bern )의 과학자들은 쥐를 이용한 동물 모델을 통해서 렘 수면이 식이 패턴에 미치는 영향을 조사했습니다. 연구팀은 렘 수면이 외측 시상하부 ( lateral hypothalamus)에 영향을 주어 식욕을 조절할 수 있다는 증거를 발견했습니다. 외측 시상하부는 모든 포유류에서 볼 수 있는 시상하부의 작은 핵으로 식욕을 조절하는데 중요한 역할을 하는 것으로 생각됩니다. 과거 과학자들은 렘 수면 동안 외측 시상하부가 활성화되는 것을 확인했지만, 렘 수면이 실제 식욕을 조절하는지에 대해서는 알지 못했습니다. 렘 수면 동안 외측 시상하부만 차단할 방법이 없었기 때문입니다.   연구팀은 빛으로 살아있는 세포를 조절하는 기술인 광유전학 (optogenetic) 방식으로 렘 수면 중인 쥐의 외측 시상하부 활동을 차단했습니다. 그 결과 쥐의 식욕이 저하되는 것을 확인할 수 있었습니다. 불과 하루 간 차단만으로도 4일 정도 효과가 지속될 정도로 식욕에 대한 영향이 컸습니다. 이는 렘 수면이 식욕을 적절하게 유지하는 데 도움을 준다는 점을 시사합니다.   사실 최근에 다이어트에 대한 수요가 폭발해서 ...

비타민 D - 우울증 예방 효과는 없다

   다른 비타민과 마찬가지로 비타민 D는 사람이 살아가는데 반드시 필요한 비타민입니다. 비타민 D가 부족한 경우 뼈에 심각한 문제가 생길 수 있습니다. 그런데 한 가지 더 흥미로운 사실은 여러 질병에서 비타민 D 부족이 관찰된다는 것입니다. 예를 들어 우울증의 경우에도 비타민 D 부족이 보고된 바 있습니다. 일부 연구자들은 햇빛을 받아 생성되는 비타민 D 부족이 계절성 우울증 장애 (seasonal affective disorder)의 원인일지 모른다고 생각해왔습니다.   하지만 하버드 의대와 메사추세스 종합 병원(MGH)의 연구팀은 비타민 D3 (cholecalciferol) 보충제를 사용한 대규모 임상 시험에서 비타민 D 복용이 우울증 예방에 특별한 효과가 없다는 사실을 확인했습니다. 이 연구는 종합 비타민제 혹은 단독으로 사용되는 비타민 D 보충제가 질병 예방에 효과가 있는지를 알아보기 위한 것으로 평균 67세의 건강한 성인 남녀 18,353명을 대상으로 진행되었습니다. 연구 참여자들은 두 그룹으로 나뉘어 콜레칼시페롤 (비타민 D3) 2000 IU 혹은 위약을 받아 5년간 복용했습니다. 우울증의 정도는 8-item Patient Health Questionnaire depression scale [PHQ-8]로 측정했습니다.   이 연구에서는 분명한 비타민 D 결핍증이 있는 경우는 제외했는데, 의학적으로 보충이 필요한 정도의 결핍이라면 치료를 하는 게 맞지 위약을 5년이나 주는 것은 윤리적으로 문제가 있기 때문입니다. 따라서 연구의 목표는 비타민이 부족하지 않은 건강한 사람에서 비타민 보충제가 혹시 우울증 예방에 효과가 있는지를 알아보려는 것입니다.   연구 결과 실험군과 대조군 사이에는 통계적으로 유의한 차이가 없었습니다. 우울증 발생률은 두 그룹에서 별로 차이가 없었으며 연구 시작과 종료 시점에 그룹 내에서도 별 차이가 없었습니다. 따라서 비타민 D가 부족하지 않...