Translate

2018년 6월 24일 일요일

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



 최근 시중에 R을 이용한 데이터 분석을 다루는 서적들이 많이 나오고 있습니다. 보통 이 서적들에서 가장 많이 다루는 패키지 가운데 하나가 바로 dplyr 입니다. 데이터를 가공하고 기본 분석 작업을 수행하는데 가장 편리한 패키지 중 하나이기 때문입니다. 물론 R의 기본 기능을 이용해서 다양한 작업을 할 수 있지만, 이렇게 널리 사용되는 패키지가 별도로 있는 건 그만큼 편리한 부분이 있기 때문입니다. 단순 선형회귀 다음에 다중 선형회귀에 대해서 설명하는 것이 순서이지만, 그전에 편리한 데이터 가공을 위해 dplyr 패키지의 기능에 대해서 설명하는 과정이 필요할 것 같습니다. 


 우리가 직접 데이터를 생성하든지 아니면 기존에 있는 데이터를 생성하든지 간에 분석을 위해서는 데이터를 가공하고 정제하는 과정이 필요합니다. 특히 이 과정은 데이터의 크기가 크고 복잡할수록 더 중요합니다. 예를 들어 관측값이 10만개 이상이고 변수도 수백가지 이상이라면 한번에 파악하기 어렵고 분석 목적에 따라 일부만 추출해야 하는 일이 흔합니다. 여기서는 단순한 예제를 위해 다이아몬드 자료에서 앞서에서처럼 50개를 추출해 어떻게 하는 지 예를 들어 보겠습니다. 


 dplyr 패키지의 가장 기본 기능인 filter는 subset과 비슷한 기능을 합니다. 원하는 조건에 따라 값을 추출해 새로운 보여주는 것입니다. 물론 subset과 동일하게 조건에 맞는 새로운 데이터를 만들 수 있습니다. 우선 패키지를 설치한 후 cut이 Ideal인 값을 뽑아보겠습니다. 

install.packages("dplyr")

library("dplyr")
library("ggplot2")

set.seed(3311)
diamonds1<-sample 50="" diamonds="" nrow="" span="">
D1<-diamonds diamonds1="" span="">
D1

D1%>%filter(cut=="Ideal")


> D1%>%filter(cut=="Ideal")
# A tibble: 18 x 10
   carat cut   color clarity depth table price     x     y     z
       
 1  0.6  Ideal F     VS1      62.9    57  2142  5.35  5.31  3.35
 2  1.01 Ideal D     SI2      62.5    57  5206  6.39  6.35  3.98
 3  0.33 Ideal G     IF       60.9    57   946  4.45  4.48  2.72
 4  0.74 Ideal D     VS2      61.8    56  3858  5.79  5.82  3.59
 5  1.2  Ideal I     VS2      63.2    59  5699  6.73  6.68  4.24
 6  1.09 Ideal G     VVS2     61.5    57  8970  6.62  6.65  4.08
 7  0.7  Ideal F     SI1      62.1    56  2573  5.65  5.67  3.51
 8  0.3  Ideal F     VS1      61.3    55   570  4.32  4.36  2.66
 9  0.31 Ideal H     IF       61.4    57   772  4.36  4.39  2.68
10  0.31 Ideal D     VS2      62.2    54   942  4.34  4.31  2.69
11  1.11 Ideal F     VS2      61.8    56  9057  6.66  6.7   4.13
12  1.09 Ideal J     SI2      62      55  5034  6.58  6.64  4.1 
13  0.32 Ideal E     VVS1     61.3    57  1020  4.43  4.38  2.7 
14  0.54 Ideal D     VS2      61.1    57  1993  5.29  5.19  3.2 
15  0.44 Ideal G     SI1      61.5    57   772  4.87  4.88  3   
16  0.41 Ideal J     VS1      62.4    55   648  4.75  4.77  2.97
17  0.62 Ideal H     VS1      63      56  1808  5.43  5.36  3.4 
18  0.33 Ideal H     VVS1     61.8    55   713  4.42  4.44  2.74


 모두 18개 관측치가 나왔습니다. 여기서 D2<-d1>%filter(cut=="Ideal") 으로 D2라는 새로운 데이터를 만들 수 있습니다. 

> D2<-d1>%filter(cut=="Ideal")
> D2
# A tibble: 18 x 10
   carat cut   color clarity depth table price     x     y     z
       
 1  0.6  Ideal F     VS1      62.9    57  2142  5.35  5.31  3.35
 2  1.01 Ideal D     SI2      62.5    57  5206  6.39  6.35  3.98
 3  0.33 Ideal G     IF       60.9    57   946  4.45  4.48  2.72
 4  0.74 Ideal D     VS2      61.8    56  3858  5.79  5.82  3.59
 5  1.2  Ideal I     VS2      63.2    59  5699  6.73  6.68  4.24
 6  1.09 Ideal G     VVS2     61.5    57  8970  6.62  6.65  4.08
 7  0.7  Ideal F     SI1      62.1    56  2573  5.65  5.67  3.51
 8  0.3  Ideal F     VS1      61.3    55   570  4.32  4.36  2.66
 9  0.31 Ideal H     IF       61.4    57   772  4.36  4.39  2.68
10  0.31 Ideal D     VS2      62.2    54   942  4.34  4.31  2.69
11  1.11 Ideal F     VS2      61.8    56  9057  6.66  6.7   4.13
12  1.09 Ideal J     SI2      62      55  5034  6.58  6.64  4.1 
13  0.32 Ideal E     VVS1     61.3    57  1020  4.43  4.38  2.7 
14  0.54 Ideal D     VS2      61.1    57  1993  5.29  5.19  3.2 
15  0.44 Ideal G     SI1      61.5    57   772  4.87  4.88  3   
16  0.41 Ideal J     VS1      62.4    55   648  4.75  4.77  2.97
17  0.62 Ideal H     VS1      63      56  1808  5.43  5.36  3.4 
18  0.33 Ideal H     VVS1     61.8    55   713  4.42  4.44  2.74

 이 기능은 subset에서도 동일하게 진행할 수 있습니다. 

> subset(D1, cut=="Ideal")
# A tibble: 18 x 10
   carat cut   color clarity depth table price     x     y     z
       
 1  0.6  Ideal F     VS1      62.9    57  2142  5.35  5.31  3.35
 2  1.01 Ideal D     SI2      62.5    57  5206  6.39  6.35  3.98
 3  0.33 Ideal G     IF       60.9    57   946  4.45  4.48  2.72
 4  0.74 Ideal D     VS2      61.8    56  3858  5.79  5.82  3.59
 5  1.2  Ideal I     VS2      63.2    59  5699  6.73  6.68  4.24
 6  1.09 Ideal G     VVS2     61.5    57  8970  6.62  6.65  4.08
 7  0.7  Ideal F     SI1      62.1    56  2573  5.65  5.67  3.51
 8  0.3  Ideal F     VS1      61.3    55   570  4.32  4.36  2.66
 9  0.31 Ideal H     IF       61.4    57   772  4.36  4.39  2.68
10  0.31 Ideal D     VS2      62.2    54   942  4.34  4.31  2.69
11  1.11 Ideal F     VS2      61.8    56  9057  6.66  6.7   4.13
12  1.09 Ideal J     SI2      62      55  5034  6.58  6.64  4.1 
13  0.32 Ideal E     VVS1     61.3    57  1020  4.43  4.38  2.7 
14  0.54 Ideal D     VS2      61.1    57  1993  5.29  5.19  3.2 
15  0.44 Ideal G     SI1      61.5    57   772  4.87  4.88  3   
16  0.41 Ideal J     VS1      62.4    55   648  4.75  4.77  2.97
17  0.62 Ideal H     VS1      63      56  1808  5.43  5.36  3.4 
18  0.33 Ideal H     VVS1     61.8    55   713  4.42  4.44  2.74


 그렇다면 왜 귀찮게 별도 패키지를 이용하는지 의문이 들 수 있으나 dplyr의 진가는 나중에 차차 설명할 것입니다. 아무튼 == 기호로 해당하는 값을 구하거나  !=으로 해당하는 값만 제외하거나 > 등 여러 기호를 통해 원하는 데이터만 추출할 수 있습니다. 


> D1%>%filter(cut!="Ideal")
# A tibble: 32 x 10
   carat cut       color clarity depth table price     x     y     z
             
 1  0.55 Very Good E     SI1      64.2    55  1417  5.18  5.2   3.33
 2  0.91 Very Good E     SI2      58.6    63  2963  6.38  6.32  3.72
 3  0.91 Good      G     VVS2     64.1    58  4543  6.06  6.1   3.9 
 4  1.5  Good      F     VS2      63.6    55 13853  7.27  7.22  4.61
 5  1.51 Premium   H     SI2      60.4    59  7864  7.3   7.27  4.4 
 6  0.45 Good      E     VS1      61.7    63  1241  4.88  4.91  3.02
 7  0.31 Premium   D     VVS2     61.7    58   988  4.39  4.33  2.69
 8  1.28 Very Good G     VVS1     60.3    59 11214  6.99  7.03  4.23
 9  1.21 Good      E     SI1      64.2    58  6708  6.65  6.59  4.25
10  1    Good      H     I1       57.6    61  2940  6.67  6.6   3.82
# ... with 22 more rows
> D1%>%filter(price>=5000)
# A tibble: 15 x 10
   carat cut       color clarity depth table price     x     y     z
             
 1  1.01 Ideal     D     SI2      62.5    57  5206  6.39  6.35  3.98
 2  1.5  Good      F     VS2      63.6    55 13853  7.27  7.22  4.61
 3  1.51 Premium   H     SI2      60.4    59  7864  7.3   7.27  4.4 
 4  1.2  Ideal     I     VS2      63.2    59  5699  6.73  6.68  4.24
 5  1.09 Ideal     G     VVS2     61.5    57  8970  6.62  6.65  4.08
 6  1.28 Very Good G     VVS1     60.3    59 11214  6.99  7.03  4.23
 7  1.21 Good      E     SI1      64.2    58  6708  6.65  6.59  4.25
 8  2    Premium   H     SI2      60.7    60 15312  8.07  8.11  4.91
 9  1.52 Very Good H     SI2      63.1    55  7600  7.36  7.28  4.62
10  2.48 Very Good F     SI2      63.4    56 18692  8.64  8.55  5.45
11  2.05 Premium   G     SI1      61.6    59 15291  8.2   8.16  5.04
12  1.11 Ideal     F     VS2      61.8    56  9057  6.66  6.7   4.13
13  1.09 Ideal     J     SI2      62      55  5034  6.58  6.64  4.1 
14  1.01 Fair      F     VS2      69      61  6041  6.06  5.99  4.16
15  1.29 Premium   I     VS1      61.1    58  5664  7.03  6.98  4.28


 subset은 각 관측치는 뽑아내도 변수만 따로 뽑기는 어렵습니다. dplyr의 select 기능을 조합하면 행과 열 모두 우리가 원하는 값을 추출할 수 있습니다. 예를 들어 cut이 Ideal인 다이이몬드에서 캐럿과 가격만 뽑아 보여줄 수 있습니다. 우선 select의 기본 문법을 보겠습니다. 앞서 보였듯이 %>%이 기본적으로 들어간다는 사실을 기억해야 합니다. D1%>%select(carat)로 캐럿만 변수를 빼낼 수 있습니다. 


> D1%>%select(carat)
# A tibble: 50 x 1
   carat
   
 1  0.6 
 2  0.55
 3  1.01
 4  0.33
 5  0.91
 6  0.91
 7  1.5 
 8  0.74
 9  1.51
10  0.45
# ... with 40 more rows


 여러 개의 변수는 각각의 변수명을 이어 붙이면 되고 만약 해당 변수만 빼고 추출할 때는 - 를 사용합니다. 


D1%>%select(carat,cut,color,clarity,price)
D1%>%select(-x,-y,-z)


 각각 해보면 결과를 쉽게 볼 수 있을 것입니다. 이제 filter와 select를 연결해서 사용해 보겠습니다. 구분은 %>% 기호로 합니다. D1%>%filter(cut=="Ideal")%>%select(carat,cut,color,clarity,price)의 구분입니다. 


> D1%>%filter(cut=="Ideal")%>%select(carat,cut,color,clarity,price)
# A tibble: 18 x 5
   carat cut   color clarity price
       
 1  0.6  Ideal F     VS1      2142
 2  1.01 Ideal D     SI2      5206
 3  0.33 Ideal G     IF        946
 4  0.74 Ideal D     VS2      3858
 5  1.2  Ideal I     VS2      5699
 6  1.09 Ideal G     VVS2     8970
 7  0.7  Ideal F     SI1      2573
 8  0.3  Ideal F     VS1       570
 9  0.31 Ideal H     IF        772
10  0.31 Ideal D     VS2       942
11  1.11 Ideal F     VS2      9057
12  1.09 Ideal J     SI2      5034
13  0.32 Ideal E     VVS1     1020
14  0.54 Ideal D     VS2      1993
15  0.44 Ideal G     SI1       772
16  0.41 Ideal J     VS1       648
17  0.62 Ideal H     VS1      1808
18  0.33 Ideal H     VVS1      713


 그런데 옆으로 길게 쓰면 코드의 가독성이 떨어집니다. %>%로 구분해서 한 칸씩 분리할 수 있습니다. 

D1%>%
  filter(cut=="Ideal")%>%  #Ideal 추출 
  select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
  head(5)

이렇게 한 칸씩 분리한 후 # 기호를 이용해서 주석을 달아주면 뭘 하는 코드인지 더 쉽게 파악이 가능합니다. 자신이 만든 코드를 나중에 해석하지 못하게 되는 일은 생각보다 비일비재한데, 이렇게 하면 쉽게 파악이 되는 것입니다. 참고로 여기서는 head를 써서 5개 값만 보여주도록 했습니다. 물론 더 쉽게 파악하기 위한 것입니다. 


> D1%>%
+   filter(cut=="Ideal")%>%  #Ideal 추출 
+   select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
+   head(5)
# A tibble: 5 x 5
  carat cut   color clarity price
     
1  0.6  Ideal F     VS1      2142
2  1.01 Ideal D     SI2      5206
3  0.33 Ideal G     IF        946
4  0.74 Ideal D     VS2      3858
5  1.2  Ideal I     VS2      5699


 여기까지만 보더라도 subset 보다 dplyr가 왜 기능이 더 많은지 이해할 수 있을 것입니다. 하지만 아직은 시작 단계입니다. 이제 dplyr의 arrange 기능을 한 줄 더 추가해 데이터를 특정값의 오름차순이나 내림차순으로 정리해 보겠습니다. 컷이 Ideal인 값을 뽑아 캐럿에 따라 순서대로 정리하겠습니다. %>%으로 줄 구분을 하고 arrange(carat)로 캐럿 순으로 오름차순 정렬합니다. 


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


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


이렇게 보니 캐럿이 커짐에 따라 다이아몬드 가격이 오르긴 하는데, 크기 이외에도 다른 여러 가지 요인에 따라 가격이 들쑥날쑥한 것을 쉽게 확인할 수 있습니다. 반대로 내림차순으로 정리하려면 arrange 안에 desc()를 더 써주면 됩니다. 


D1%>%
  filter(cut=="Ideal")%>%  #Ideal 추출 
  select(carat,cut,color,clarity,price)%>% # 캐럿, 컷, 칼러, 채도, 가격 추출
  arrange(desc(carat)) #내림차순 정렬


노파심에서 말하면 콘솔 창에서는 코드가 이렇게 보여야 합니다. 




 참고로 filter 기능은 |, >,<,= 등 여러 기호를 통해 다양한 조건을 검색할 수 있습니다. 


D1%>%filter(cut!="Ideal")
D1%>%filter(price>=5000)

D1%>%filter(price>=5000 & cut=="Ideal")
D1%>%filter(cut=="Ideal"|cut=="Premium")


 이 코드는 대표적인 방식을 설명한 것입니다. 아무튼 이렇게 하면 상당히 자유자재로 데이터를 가공할 수 있다는 느낌이 듭니다. 하지만 dplyr의 기능은 당연히 여기서 끝이 아닙니다. 다음에 확장 기능에 대해서 알아보겠습니다. 

댓글 없음:

댓글 쓰기