패키지 dplyr 01: 부분선택(subsetting)
dplyr 패키지를 활용한 데이터 가공 01: 부분 선택하기(Subsetting)
dplyr 패키지
dplyr패키지의slice,filter,select,mutate,arrange,summarize,group_by,do등의 함수는 데이터 가공을 도와준다. 특히 이름에서 쉽게 연상되는 기능으로 초보자도 쉽게 코드를 읽을 수 있다. 특히%>%와 함께 사용하면 코드를 직관적으로 이해는데 도움이 된다. 여기서는mtcars데이터를 활용하여dplyr패키지와%>%를 활용하여 데이터를 가공하는 법을 살펴본다.
library(dplyr)
data(mtcars)
tb = as_tibble(mtcars)
dplyr패키지의 함수는 입력을 티블로 변환하여 처리한다. 여기서는as_tibble함수를 사용하여 미리 티블 형식으로 바꾸었다.
행의 순서로 데이터의 부분 참조
- 데이터 테이블
tb의 두 번째에서 다섯 번째 행을 참조하려면tb[2:5,]로 쓰면
된다.slice함수를 쓴다면slice(tb, 2:5)이 된다.
tb[2:5, ]
## # A tibble: 4 x 11 ## mpg cyl disp hp drat wt qsec vs am gear carb ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 21 6 160 110 3.9 2.88 17.0 0 1 4 4 ## 2 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1 ## 3 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1 ## 4 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
slice(tb, 2:5)
## # A tibble: 4 x 11 ## mpg cyl disp hp drat wt qsec vs am gear carb ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 21 6 160 110 3.9 2.88 17.0 0 1 4 4 ## 2 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1 ## 3 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1 ## 4 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
이를 %>%와 함께 쓴다면 다음과 같다.
tb %>% .[2:5, ]
tb %>% slice(., 2:5)
위의 slice(., 2:5)의 경우 .이 첫 번째 인자이므로 생략할 수 있다.
tb %>% slice(2:5)
tb %>% slice(c(2:3, 4, 5))
논리 벡터를 사용하여 행 부분 참조
mtcar(또는 티블 형식tb)에서mpg가30초과인 행만을 뽑아 보고 싶다. 데이터프레임에서 자주 사용하는 방법은tb[tb$mpg>30, ]이다.filter함수를 사용하면filter(tb, mpg>30)또는tb %>% filter(., mpg>30)이 된다..를 생략한다면tb %>% filter(mpg>30)이 된다.
tb[tb$mpg>30, ]
## # A tibble: 4 x 11 ## mpg cyl disp hp drat wt qsec vs am gear carb ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 32.4 4 78.7 66 4.08 2.2 19.5 1 1 4 1 ## 2 30.4 4 75.7 52 4.93 1.62 18.5 1 1 4 2 ## 3 33.9 4 71.1 65 4.22 1.84 19.9 1 1 4 1 ## 4 30.4 4 95.1 113 3.77 1.51 16.9 1 1 5 2
- 다음은 모두 위의 코드와 동일한 결과를 보여준다.
filter(tb, mpg>30)
tb %>% filter(., mpg>30)
tb %>% filter(mpg>30)
열 이름이나 번호로 부분 참조
- 티블 데이터
tb에서 첫 번째 와 세 번째 열을 보고 싶다면 데이터 프레임처럼tb[, c(1,3)]을 사용할 수 있다.dplyr의select함수를 사용하면select(tb, c(1,3))이 된다.%>%를 사용하면,tb %>% select(c(1,3))이 된다.
tb <- tb %>% slice(3:5)
tb[, c(1,3)]
select(tb, c(1,3))
tb %>% select(c(1,3))
## # A tibble: 3 x 2 ## mpg disp ## <dbl> <dbl> ## 1 22.8 108 ## 2 21.4 258 ## 3 18.7 360
- 열 이름을 사용하고 싶다면 다음과 같다.
select함수를 사용할 때에는 열이름에 따옴표 ("또는')를 생략할 수 있다. 그리고 열이름을 하나의 벡터로 만들 필요도 없다. 다음은 모두 동일한 결과를 보여준다.
tb[, c("cyl", "hp")]
select(tb, c("cyl", "hp"))
select(tb, c(cyl, hp))
tb %>% select(c("cyl", "hp"))
tb %>% select(c(cyl, hp))
tb %>% select("cyl", "hp")
tb %>% select(cyl, hp)
select의 좋은 점의 하나는 열이름에:을 쓸 수 있다는 점이다. 예를 들어 데이터 프레임tb에서 열이름hp에서 열이름qsec까지를 선택하고 싶다고 해보자. 열의 순번을 안다면tb %>% select(4:7)을 할 수 있다(hp는tb의 4번째 열이고,qsec는tb의 7번째 열이다). 하지만 열의 순번을 모른다면? 열의 수가 굉장히 많은 데이터에서 열의 순번을 파악하는 것이 생각만큼 쉽지 않다.
which(colnames(tb)=='hp'); which(colnames(tb)=='qsec')
## [1] 4
## [1] 7
tb[, which(colnames(tb)=='hp'):which(colnames(tb)=='qsec')]
## # A tibble: 3 x 4
## hp drat wt qsec
## <dbl> <dbl> <dbl> <dbl>
## 1 93 3.85 2.32 18.6
## 2 110 3.08 3.22 19.4
## 3 175 3.15 3.44 17.0
select를 사용한다면 간단하게select(hp:qsec)으로 쓸 수 있다. (하지만select('hp':'qsec')은 쓸 수 없음을 주의하자.
tb %>% select(hp:qsec)
## # A tibble: 3 x 4 ## hp drat wt qsec ## <dbl> <dbl> <dbl> <dbl> ## 1 93 3.85 2.32 18.6 ## 2 110 3.08 3.22 19.4 ## 3 175 3.15 3.44 17.0
마지막으로 select는 참조하고자 하는 열이름을 하나의 벡터로 만들지 않아도 되지만, slice의 경우는 그렇지 않다는 점에 유의하자.
slice(tb, c(5,7))
## # A tibble: 0 x 11 ## # ... with 11 variables: mpg <dbl>, cyl <dbl>, disp <dbl>, hp <dbl>, ## # drat <dbl>, wt <dbl>, qsec <dbl>, vs <dbl>, am <dbl>, gear <dbl>, ## # carb <dbl>
slice(tb, 5, 7)
## Error in slice_impl(.data, dots): slice only accepts one expression
특정한 조건을 만족하는 열 이름 참조
select함수 안에 다음의 함수를 써서 열이름이 특정한 조건을 만족하는 열만 선별할 수 있다. 먼저 이해하기 쉬운starts_with( ),ends_with( ),contains_with( )를 보자. 다음의 예로 충분히 이해할 수 있을 것이다.
| 구문 | 의미 |
|---|---|
starts_with('ab') |
ab로 시작하는 |
ends_with('yz') |
yz로 끝나는 |
contains_with('ef') |
ef를 포함하는 |
one_of(coln) |
문자열 벡터 coln의 각 원소와 일치하는 |
matches('..[cd]') |
정규표현식 ..[cd]에 대응하는 |
tb3 <- tb %>% slice(1:3)
tb3
## # A tibble: 3 x 11 ## mpg cyl disp hp drat wt qsec vs am gear carb ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1 ## 2 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1 ## 3 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
tb3 %>% select(starts_with('c'))
## # A tibble: 3 x 2 ## cyl carb ## <dbl> <dbl> ## 1 4 1 ## 2 6 1 ## 3 8 2
tb3 %>% select(starts_with('ca'))
## # A tibble: 3 x 1 ## carb ## <dbl> ## 1 1 ## 2 1 ## 3 2
tb3 %>% select(ends_with('p'))
## # A tibble: 3 x 2 ## disp hp ## <dbl> <dbl> ## 1 108 93 ## 2 258 110 ## 3 360 175
tb3 %>% select(contains('c'))
## # A tibble: 3 x 3 ## cyl qsec carb ## <dbl> <dbl> <dbl> ## 1 4 18.6 1 ## 2 6 19.4 1 ## 3 8 17.0 2
select함수를 쓰면 열이름을 따옴표 없이 쓸 수 있다는 장점이 있다. 하지만 열이름을 저장하는 문자 벡터를 사용하려면 어떻게 해야 하는가? 보통은'mpg'로 쓰면 열이름이mpg라는 의미이고,mpg는mpg라는 변수를 의미한다. 하지만select함수 안에서는mpg는 열이름mpg를 나타낸다. 만약mpg벡터를 의미하고 싶다면one_of()함수를 사용한다. (여기서는 열이름을 나타내는 벡터로coln을 사용하였다. colname을 의미하는 이름이다.)
coln <- c('drat', 'qsec')
tb3 %>% select(one_of(coln))
## # A tibble: 3 x 2 ## drat qsec ## <dbl> <dbl> ## 1 3.85 18.6 ## 2 3.08 19.4 ## 3 3.15 17.0
matches()함수는 정규표현식을 사용하여 열이름을 선택하기 위해 사용한다.
예를 들어 정규표현식 ^(.s|.{4})는 두번째 문자가 s이거나 네문자로 이루어진 경우를 나타낸다. 이를 사용해서 열을 선택하면 다음과 같다.
tb3 %>% select(matches('^(.s|.{4})'))
## # A tibble: 3 x 6 ## disp drat qsec vs gear carb ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 108 3.85 18.6 1 4 1 ## 2 258 3.08 19.4 1 3 1 ## 3 360 3.15 17.0 0 3 2
이런 함수(starts_with, ends_with 등)의 도움 없이 동일한 열을 선택하고자 한다면 보통 정규표현식을 사용하게 된다. 동일한 역할을 앞에서 소개한 함수를 사용한 경우와 정규표현식을 사용한 경우를 비교해보면 다음과 같다.
dplyr의 함수 |
정규표현식 |
|---|---|
tb %>% select(starts_with('c')) |
tb[, grep('^c', colnames(tb)] |
tb %>% select(ends_with('p')) |
tb[, grep('p$', colnames(tb))] |
tb %>% select(contains('c')) |
tb[, grep('c', colnames(tb))] |
특정한 열 이름 제외
- 만약
cyl,qsec을 제외한 나머지 열을 선택하고 싶다면 다음의 두 방법을 사용할 수 있다.
tb %>% select(-cyl, -qsec)
## # A tibble: 3 x 9 ## mpg disp hp drat wt vs am gear carb ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 22.8 108 93 3.85 2.32 1 1 4 1 ## 2 21.4 258 110 3.08 3.22 1 0 3 1 ## 3 18.7 360 175 3.15 3.44 0 0 3 2
tb %>% select(-c(cyl, qsec))
## # A tibble: 3 x 9 ## mpg disp hp drat wt vs am gear carb ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 22.8 108 93 3.85 2.32 1 1 4 1 ## 2 21.4 258 110 3.08 3.22 1 0 3 1 ## 3 18.7 360 175 3.15 3.44 0 0 3 2
- 특정한 조건을 만족하는 열 이름을 제외하고 싶다면 위에서 소개한 함수
starts_with,ends_with등의 앞에-를 붙인다.
tb %>% select(-starts_with('c'))
## # A tibble: 3 x 9 ## mpg disp hp drat wt qsec vs am gear ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 22.8 108 93 3.85 2.32 18.6 1 1 4 ## 2 21.4 258 110 3.08 3.22 19.4 1 0 3 ## 3 18.7 360 175 3.15 3.44 17.0 0 0 3
tb %>% select(-ends_with('p'))
## # A tibble: 3 x 9 ## mpg cyl drat wt qsec vs am gear carb ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 22.8 4 3.85 2.32 18.6 1 1 4 1 ## 2 21.4 6 3.08 3.22 19.4 1 0 3 1 ## 3 18.7 8 3.15 3.44 17.0 0 0 3 2
tb %>% select(-contains('c'))
## # A tibble: 3 x 8 ## mpg disp hp drat wt vs am gear ## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 22.8 108 93 3.85 2.32 1 1 4 ## 2 21.4 258 110 3.08 3.22 1 0 3 ## 3 18.7 360 175 3.15 3.44 0 0 3
Leave a comment