최근 시중에 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="">-sample>
D1<-diamonds diamonds1="" span="">-diamonds>
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라는 새로운 데이터를 만들 수 있습니다. -d1>
> D2<-d1>%filter(cut=="Ideal")-d1>
> 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의 기능은 당연히 여기서 끝이 아닙니다. 다음에 확장 기능에 대해서 알아보겠습니다.
댓글
댓글 쓰기