패키지 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