본문 바로가기
  • plotly로 바로쓰는 동적시각화 in R & 파이썬
데이터 전처리

tidyverse를 사용한 열 선택 방법

by 아참형인간 2021. 6. 27.
select1.utf8

tidyverse로 열 선택

R 사용자들은 데이터프레임을 다룰때 가장 많이 사용하는 패키지가 tidyverse 패키지일 것이다. tidyverse 패키지는 데이터프레임에 저장된 데이터를 다루는 순차적이고 쉬운 방법을 제공하기 때문에 많은 사용자가 사용하지만 tidyverse를 소개하는 많은 책에서는 가장 기초적인 함수인 select(), filter(), group_by(), summarise(), mutate()의 다섯가지 함수를 소개하는 경우가 대부분이다. 하지만 tidyverse는 더 많은 기능을 가진 패키지이다.

이번 포스트에서는 tidyverseselect()를 사용하여 열을 선택하는 여러가지 방법을 설명한다.

이 포스트에서 사용하는 샘플 데이터는 교육통계 홈페이지에서 제공하는 시도별 행정구별 주요 교육 통계 현황(2010~2020)에서 제공하는 엑셀파일을 사용하였다. 해당 페이지에서 다운받은 엑셀파일에서 데이터를 로딩하는 코드는 다음과 같다.

library(readxl)
data <- read_xlsx('./주요 교육통계자료 행정구역별 2010-2020(탑재용)_201124.xlsx', sheet = '2020', skip = 5, col_types = c(rep('text', 4), rep('numeric', 33)), col_names = FALSE)
names(data) <- c('기준일', '시도', '시군구', '학교급', '학교수', '학급수_계', '학급수_1학년', '학급수_2학년', '학급수_3학년', '학급수_4학년', '학급수_5학년', '학급수_6학년', '학생수_계_계', '학생수_계_여', '학생수_1학년_계', '학생수_1학년_여', '학생수_2학년_계', '학생수_2학년_여', '학생수_3학년_계', '학생수_3학년_여', '학생수_4학년_계', '학생수_4학년_여', '학생수_5학년_계', '학생수_5학년_여', '학생수_6학년_계', '학생수_6학년_여', '교원수_계', '교원수_여', '다문화학생수_계', '다문화학생수_여', '학업중단자_계', '학업중단자_여', '학업중단자_유예', '학업중단자_면제', '학업중단자_자퇴', '학업중단자_퇴학', '학업중단자_제적')

열 이름, 번호로 선택하기

tidyverseselect()를 사용해서 특정 열을 선택하는 기본적인 방법은 열 이름이나 열 번호를 사용하는 방법이다. 위에서 import한 데이터에서 기본정보(기준일, 시도, 시군구, 학교급)와 학급수만을 선택하는 코드는 다음과 같다.

library(tidyverse)
### 열 이름을 사용하는 방법
data %>%
  select(c('기준일', '시도', '시군구', '학교급', '학급수_계', '학급수_1학년', '학급수_2학년', '학급수_3학년', '학급수_4학년', '학급수_5학년', '학급수_6학년')) %>%
  head
## # A tibble: 6 x 11
##   기준일   시도  시군구 학교급  학급수_계 학급수_1학년 학급수_2학년 학급수_3학년
##   <chr>    <chr> <chr>  <chr>       <dbl>        <dbl>        <dbl>        <dbl>
## 1 20200401 서울  종로구 유치원         64            0            0            0
## 2 20200401 서울  종로구 초등학~       269           43           44           40
## 3 20200401 서울  종로구 중학교        134           45           44           45
## 4 20200401 서울  종로구 고등학~       367          119          123          125
## 5 20200401 서울  종로구 (일반~        162           52           55           55
## 6 20200401 서울  종로구 (특목~         72           24           24           24
## # ... with 3 more variables: 학급수_4학년 <dbl>, 학급수_5학년 <dbl>,
## #   학급수_6학년 <dbl>
### 열 번호을 사용하는 방법 - 1
data %>%
  select(c(1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12)) %>%
  head
## # A tibble: 6 x 11
##   기준일   시도  시군구 학교급  학급수_계 학급수_1학년 학급수_2학년 학급수_3학년
##   <chr>    <chr> <chr>  <chr>       <dbl>        <dbl>        <dbl>        <dbl>
## 1 20200401 서울  종로구 유치원         64            0            0            0
## 2 20200401 서울  종로구 초등학~       269           43           44           40
## 3 20200401 서울  종로구 중학교        134           45           44           45
## 4 20200401 서울  종로구 고등학~       367          119          123          125
## 5 20200401 서울  종로구 (일반~        162           52           55           55
## 6 20200401 서울  종로구 (특목~         72           24           24           24
## # ... with 3 more variables: 학급수_4학년 <dbl>, 학급수_5학년 <dbl>,
## #   학급수_6학년 <dbl>
### 열 번호을 사용하는 방법 - 2
data %>%
  select(c(seq(1, 4), seq(6, 12))) %>%
  head
## # A tibble: 6 x 11
##   기준일   시도  시군구 학교급  학급수_계 학급수_1학년 학급수_2학년 학급수_3학년
##   <chr>    <chr> <chr>  <chr>       <dbl>        <dbl>        <dbl>        <dbl>
## 1 20200401 서울  종로구 유치원         64            0            0            0
## 2 20200401 서울  종로구 초등학~       269           43           44           40
## 3 20200401 서울  종로구 중학교        134           45           44           45
## 4 20200401 서울  종로구 고등학~       367          119          123          125
## 5 20200401 서울  종로구 (일반~        162           52           55           55
## 6 20200401 서울  종로구 (특목~         72           24           24           24
## # ... with 3 more variables: 학급수_4학년 <dbl>, 학급수_5학년 <dbl>,
## #   학급수_6학년 <dbl>

특정 문자열로 시작하는 열 선택

일반적으로 유사한 데이터 열은 이름이 비슷하게 작명한다. 위의 예에서 학급수에 관련된 열은 모두 ’학급수’로 시작하고 있는데 ’학급수’로 시작하는 열만을 선택하기 위해서는 starts_with()를 사용한다.

data %>%
  select(c(1, 2, 3, 4, starts_with('학급수'))) %>%
  head
## # A tibble: 6 x 11
##   기준일   시도  시군구 학교급  학급수_계 학급수_1학년 학급수_2학년 학급수_3학년
##   <chr>    <chr> <chr>  <chr>       <dbl>        <dbl>        <dbl>        <dbl>
## 1 20200401 서울  종로구 유치원         64            0            0            0
## 2 20200401 서울  종로구 초등학~       269           43           44           40
## 3 20200401 서울  종로구 중학교        134           45           44           45
## 4 20200401 서울  종로구 고등학~       367          119          123          125
## 5 20200401 서울  종로구 (일반~        162           52           55           55
## 6 20200401 서울  종로구 (특목~         72           24           24           24
## # ... with 3 more variables: 학급수_4학년 <dbl>, 학급수_5학년 <dbl>,
## #   학급수_6학년 <dbl>

특정 문자열로 끝나는 열 선택 방법

샘플 데이터에서 남여가 구분되는 데이터의 경우 여성 데이터는 열 이름 뒤에 ’여’가 붙는다 이와 같이 유사한 열의 세부항목을 구분할 때 열 이름의 뒤에 특성 이름을 붙이는 경우도 있다. 이런 경우는 ends_with()를 사용한다.

data %>%
  select(c(1, 2, 3, 4, ends_with('여'))) %>%
  head
## # A tibble: 6 x 14
##   기준일   시도  시군구 학교급   학생수_계_여 학생수_1학년_여 학생수_2학년_여
##   <chr>    <chr> <chr>  <chr>           <dbl>           <dbl>           <dbl>
## 1 20200401 서울  종로구 유치원            588               0               0
## 2 20200401 서울  종로구 초등학교         2558             383             456
## 3 20200401 서울  종로구 중학교           1296             452             441
## 4 20200401 서울  종로구 고등학교         3692            1288            1241
## 5 20200401 서울  종로구 (일반고)         1656             559             589
## 6 20200401 서울  종로구 (특목고)         1260             433             421
## # ... with 7 more variables: 학생수_3학년_여 <dbl>, 학생수_4학년_여 <dbl>,
## #   학생수_5학년_여 <dbl>, 학생수_6학년_여 <dbl>, 교원수_여 <dbl>,
## #   다문화학생수_여 <dbl>, 학업중단자_여 <dbl>

특정 문자열을 포함하는 열 선택 방법

앞에서 설명한 두 가지 방법외에 특정 문자열이 열 이름에 포함된 열을 선택할 때는 contains()를 사용한다. 위의 예에서 ’학생수’를 포함하는 열을 선택하는 코드는 다음과 같다.

data %>%
  select(c(1, 2, 3, 4, contains('학생수'))) %>%
  head
## # A tibble: 6 x 20
##   기준일   시도  시군구 학교급   학생수_계_계 학생수_계_여 학생수_1학년_계
##   <chr>    <chr> <chr>  <chr>           <dbl>        <dbl>           <dbl>
## 1 20200401 서울  종로구 유치원           1180          588               0
## 2 20200401 서울  종로구 초등학교         5192         2558             764
## 3 20200401 서울  종로구 중학교           2793         1296             988
## 4 20200401 서울  종로구 고등학교         8467         3692            2839
## 5 20200401 서울  종로구 (일반고)         3531         1656            1136
## 6 20200401 서울  종로구 (특목고)         1908         1260             651
## # ... with 13 more variables: 학생수_1학년_여 <dbl>, 학생수_2학년_계 <dbl>,
## #   학생수_2학년_여 <dbl>, 학생수_3학년_계 <dbl>, 학생수_3학년_여 <dbl>,
## #   학생수_4학년_계 <dbl>, 학생수_4학년_여 <dbl>, 학생수_5학년_계 <dbl>,
## #   학생수_5학년_여 <dbl>, 학생수_6학년_계 <dbl>, 학생수_6학년_여 <dbl>,
## #   다문화학생수_계 <dbl>, 다문화학생수_여 <dbl>

정규표현식(regular expression)을 사용한 열 선택 방법

특정 패턴을 가지는 문자열을 골라낼때는 정규표현식을 사용한다. 열 이름을 선택할 때 정규표현식을 사용하기 위해서는 matches()를 사용한다. 다음은 열 이름에 숫자가 들어간 열을 선택하는 코드이다.

data %>%
  select(c(1, 2, 3, 4, matches('[1-9]'))) %>%
  head
## # A tibble: 6 x 22
##   기준일 시도  시군구 학교급 학급수_1학년 학급수_2학년 학급수_3학년 학급수_4학년
##   <chr>  <chr> <chr>  <chr>         <dbl>        <dbl>        <dbl>        <dbl>
## 1 20200~ 서울  종로구 유치원            0            0            0            0
## 2 20200~ 서울  종로구 초등~            43           44           40           46
## 3 20200~ 서울  종로구 중학교           45           44           45            0
## 4 20200~ 서울  종로구 고등~           119          123          125            0
## 5 20200~ 서울  종로구 (일반~           52           55           55            0
## 6 20200~ 서울  종로구 (특목~           24           24           24            0
## # ... with 14 more variables: 학급수_5학년 <dbl>, 학급수_6학년 <dbl>,
## #   학생수_1학년_계 <dbl>, 학생수_1학년_여 <dbl>, 학생수_2학년_계 <dbl>,
## #   학생수_2학년_여 <dbl>, 학생수_3학년_계 <dbl>, 학생수_3학년_여 <dbl>,
## #   학생수_4학년_계 <dbl>, 학생수_4학년_여 <dbl>, 학생수_5학년_계 <dbl>,
## #   학생수_5학년_여 <dbl>, 학생수_6학년_계 <dbl>, 학생수_6학년_여 <dbl>

특정 문자열을 제외한 열 선택 방법

지금까지는 특정 문자열을 포함한 열을 선택하는 방법을 알아보았다. 하지만 특정 문자열로 시작하거나, 끝나거나, 포함한 열만을 제외하고 나머지 열을 선택해야하는 경우도 있다. 예를 들어 위의 예에서 ’교원수’가 들어간 열을 제외한 나머지 열을 모두 선택해야 하는 경우이다. 이런 경우는 연산자 !를 사용할 수 있다.

data %>%
  select(!contains('교원수')) %>%
  head
## # A tibble: 6 x 35
##   기준일   시도  시군구 학교급   학교수 학급수_계 학급수_1학년 학급수_2학년
##   <chr>    <chr> <chr>  <chr>     <dbl>     <dbl>        <dbl>        <dbl>
## 1 20200401 서울  종로구 유치원       17        64            0            0
## 2 20200401 서울  종로구 초등학교     13       269           43           44
## 3 20200401 서울  종로구 중학교        9       134           45           44
## 4 20200401 서울  종로구 고등학교     14       367          119          123
## 5 20200401 서울  종로구 (일반고)      6       162           52           55
## 6 20200401 서울  종로구 (특목고)      3        72           24           24
## # ... with 27 more variables: 학급수_3학년 <dbl>, 학급수_4학년 <dbl>,
## #   학급수_5학년 <dbl>, 학급수_6학년 <dbl>, 학생수_계_계 <dbl>,
## #   학생수_계_여 <dbl>, 학생수_1학년_계 <dbl>, 학생수_1학년_여 <dbl>,
## #   학생수_2학년_계 <dbl>, 학생수_2학년_여 <dbl>, 학생수_3학년_계 <dbl>,
## #   학생수_3학년_여 <dbl>, 학생수_4학년_계 <dbl>, 학생수_4학년_여 <dbl>,
## #   학생수_5학년_계 <dbl>, 학생수_5학년_여 <dbl>, 학생수_6학년_계 <dbl>,
## #   학생수_6학년_여 <dbl>, 다문화학생수_계 <dbl>, 다문화학생수_여 <dbl>,
## #   학업중단자_계 <dbl>, 학업중단자_여 <dbl>, 학업중단자_유예 <dbl>,
## #   학업중단자_면제 <dbl>, 학업중단자_자퇴 <dbl>, 학업중단자_퇴학 <dbl>,
## #   학업중단자_제적 <dbl>

벡터에 포함된 문자열을 가진 열 선택 방법

선택해야할 열이름이 저장된 문자열 벡터가 있을 경우 이 벡터에 있는 모든 열을 선택하기 위해서는 다음과 같이 all_of()를 사용할 수 있다.

선택열 <- c('기준일', '시도', '학교급')
data %>%
  select(all_of(선택열)) %>%
  head
## # A tibble: 6 x 3
##   기준일   시도  학교급  
##   <chr>    <chr> <chr>   
## 1 20200401 서울  유치원  
## 2 20200401 서울  초등학교
## 3 20200401 서울  중학교  
## 4 20200401 서울  고등학교
## 5 20200401 서울  (일반고)
## 6 20200401 서울  (특목고)

하지만 다음과 같이 all_of()를 사용하지 않는다 해도 동일한 결과를 얻을 수 있다.

data %>%
  select(선택열) %>%
  head
## # A tibble: 6 x 3
##   기준일   시도  학교급  
##   <chr>    <chr> <chr>   
## 1 20200401 서울  유치원  
## 2 20200401 서울  초등학교
## 3 20200401 서울  중학교  
## 4 20200401 서울  고등학교
## 5 20200401 서울  (일반고)
## 6 20200401 서울  (특목고)

그렇다면 all_of()를 쓰는 이유는 무엇인가? 아래와 같이 열이름을 포함한 벡터가 열이름과 동일한 경우 그 차이가 있다.

기준일 <- c('기준일', '시도', '학교급')
data %>%
  select(all_of(기준일)) %>%
  head
## # A tibble: 6 x 3
##   기준일   시도  학교급  
##   <chr>    <chr> <chr>   
## 1 20200401 서울  유치원  
## 2 20200401 서울  초등학교
## 3 20200401 서울  중학교  
## 4 20200401 서울  고등학교
## 5 20200401 서울  (일반고)
## 6 20200401 서울  (특목고)
data %>%
  select(기준일) %>%
  head
## # A tibble: 6 x 1
##   기준일  
##   <chr>   
## 1 20200401
## 2 20200401
## 3 20200401
## 4 20200401
## 5 20200401
## 6 20200401

만약 열이름 벡터에 존재하지 않는 열이름이 포함되는 경우는 다음과 같이 에러를 발생시킨다.

선택열 <- c('기준일', '시도', '학교급', '학생수')
data %>%
  select(all_of(선택열)) %>%
  head
## Error: Can't subset columns that don't exist.
## x Column `학생수` doesn't exist.

이런 경우는 any_of()를 사용하는데 all_of()와 동일한 함수이지만 에러 체크를 하지 않는다는 점에서 차이가 있다.

data %>%
  select(any_of(선택열)) %>%
  head
## # A tibble: 6 x 3
##   기준일   시도  학교급  
##   <chr>    <chr> <chr>   
## 1 20200401 서울  유치원  
## 2 20200401 서울  초등학교
## 3 20200401 서울  중학교  
## 4 20200401 서울  고등학교
## 5 20200401 서울  (일반고)
## 6 20200401 서울  (특목고)

댓글