이번 포스팅에서는 데이터 전처리 과정 중에서


(1) 기준이 되는 단위나 그룹 별로 관측치의 개수를 구해서

(2) 그룹 별 관측치 개수가 1개인 그룹의 DataFrame 과 2개 이상인 그룹의 DataFrame을 구분


해서 생성하는 방법을 소개하겠습니다.


dplyr 패키지를 이용해서 chain operator (%>%) 로 한꺼번에 코드를 짜면 편리합니다. dplyr 패키지의 group_by(), mutate(), filter(), select() 등의 여러개의 함수를 사용하였습니다.


(그룹 별 관측치 개수를 구해서 먼저 DataFrame으로 만들어놓고, 그 다음에 merge 함수를 이용해서 그룹별로 관측치 개수를 원본 DataFrame에 합쳐준 후에, 조건문으로 그룹별 관측치 개수별로 DataFrame을 구분해서 생성해주는 방식으로 step by step 진행해도 됩니다.)





먼저, dplyr 패키지를 불러오고, 간단한 예제 DataFrame을 만들어보겠습니다. 이때 칼럼 'id'가 관측치 개수를 세는 기준이 되는 그룹이 되겠습니다.



library(dplyr)

id <- c("A", "B", "C", "C", "D", "E", "E", "E")
x1 <- c(3, 2, 1, 1, 3, 3, 2, 4)
x2 <- c(60, 20, 30, 10, 70, 10, 20, 30)

df <- data.frame(id, x1 x2)
df
# id x1 x2
# 1  A  3 60
# 2  B  2 20
# 3  C  1 30
# 4  C  1 10
# 5  D  3 70
# 6  E  3 10
# 7  E  2 20
# 8  E  4 30

 




  (1) 단위 그룹별로 관측치 개수 구하기


(a) dplyr 패키지의 group_by() 함수에 관측치 개수를 세는 단위 기준이 되는 그룹변수 'id' 를 넣어주고,


(b) mutate() 함수의 n() 매개변수로 관측치 개수(number of rows)를 세어서 'n'이라는 이름의 새로운 변수를 만들어줍니다.


(c) 그리고 filter() 함수를 사용해서 위의 (b)에서 새로 만든 그룹별 관측치 개수 'n'에 대해 조건 '관측치 개수가 1개인 조건 (n == 1)' 을 만족하는 행만 걸러내는 원리입니다.



df %>%
  group_by(id) %>%
  mutate(n = n()) %>%
  filter(n == 1)


# # A tibble: 3 x 4
# # Groups:   id [3]
# id       x1    x2     n
# <chr> <dbl> <dbl> <int>
# 1 A         3    60     1
# 2 B         2    20     1
# 3 D         3    70     1






  (2) 단위 그룹별로 관측치 개수가 1개 vs. 2개 이상인 그룹 구분해서 DataFrame 만들기


우리가 원하는 최종 산출물은 단위 그룹별 관측치 개수는 필요하지 않으므로 (d) select(id, x1, x2) 함수를 사용해서 원본 데이터에 있는 변수들만 선택해서 가져오겠습니다.


그리고 그룹별 관측치 개수가 1개인 관측치만으로 이루어진 'df_1' 라는 이름의 DataFrame과, 그룹별 관측치 개수가 2개 이상인 관측치들로 이루어진 'df_2' 라는 이름의 DataFrame을 각각 구분해서 생성해보겠습니다.


dplyr 패키지의 체인 연산(%>%) 으로 한꺼번에 코드를 짤 수 있으므로 코드가 단순하고 가독성이 좋습니다.



## data.frame which has only 1 observation by x1 category
df_1 <- df %>%
  group_by(id) %>%
  mutate(n = n()) %>%
  filter(n == 1) %>%
  select(id, x1, x2)

df_1
# id       x1    x2
# <chr> <dbl> <dbl>
# 1 A         3    60
# 2 B         2    20
# 3 D         3    70


# data.frame which has more than 2 observations by x1 categories
df_2 <- df %>%
  group_by(id) %>%
  mutate(n = n()) %>%
  filter(n >= 2) %>%
  select(id, x1, x2)

df_2
# id       x1    x2
# <chr> <dbl> <dbl>
# 1 C         1    30
# 2 C         1    10
# 3 E         3    10
# 4 E         2    20
# 5 E         4    30



[ Reference ]

* R dplyr 패키지 기본함수 소개: https://rfriend.tistory.com/234

* R dplyr 패키지의 새로운 변수만들기 소개: https://rfriend.tistory.com/235

* R dplyr 패키지의 chain operator (or pipe operator) 소개: https://rfriend.tistory.com/236

* R dplyr 패키지의 그룹별 행의 개수 세기 소개: https://rfriend.tistory.com/240



다음 포스팅에서는 이번 포스팅과 동일한 결과를 얻기위해 R data.table 패키지를 사용해서 그룹별 관측치 개수별로 data.table을 구분해서 생성하는 방법(https://rfriend.tistory.com/607)을 소개하겠습니다.


이번 포스팅이 많은 도움이 되었기를 바랍니다.

행복한 데이터 과학자 되세요!  :-)



728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 데이터프레임(dataframe)을 위한 데이터 전처리, 조작(data pre-processing, data manipulation)을 쉽고! 빠르게! 할 수 있도록 해주는 dplyr 패키지에 대해서 알아보겠습니다.

 

R help에 검색해보면 dplyr 패키지를 아래와 같이 소개하고 있습니다.

 

dplyr은 유연한 데이터 조작의 문법을 제공합니다.  이것은 plyr의 차기작으로서, 데이터프레임을 집중적으로 다루는 툴입니다

 

dplyr provides a flexible grammar of data manipulation. It's the next iteration of plyr, focused on tools for working with data frames (hence the d in the name)

 

 

데이터 조작을 위한 문법으로 체계화를 해서 한번 배워놓으면 쉽다는 점과 더불어, C언어로 만들어서 매우 빠르다는 점도 dplyr 패키지의 크나큰 장점 중의 하나입니다.

 

 

 

아마 R을 좀 다룬 분이라면은 그래프/시각화를 문법으로 승화시켜서 체계를 잡아놓은 "ggplot2" package ( "ggplot is an implementation of the grammer of Graphics in R")를 알고 계실텐데요, 이 ggplot2를 만든 그 유명한 Hadley Wickham 이 dplyr 패키지도 만들었습니다.  

 

아래에 소개한 것처럼, r-bloggers.com에 소개되어 있는 Hadley 인 인터뷰를 보면, 기존 통계학에서는 데이터 전처리(Data munging and manipulation)를 "내 일이 아니야"라고 무시했었다고 합니다. 그런데 Hadley Wickham이 보기에는 모델링과 시각화로 부터 통찰을 끄집에 내는데 있어서 데이터 조작, 전처리가 매우 중요하고 또 어려운 영역이라고 보기에 Hadley가 직접 나서서 이를 도와줄 수 있는 R packages를 만들었다고 나오네요.  ^^b

"Hadley Wickham on why he created all those R packages"

July 27, 2015 By David Smith

 

“There are definitely some academic statisticians who just don’t understand why what I do is statistics, but basically I think they are all wrong . What I do is fundamentally statistics. The fact that data science exists as a field is a colossal failure of statistics.

 

To me, that is what statistics is all about. It is gaining insight from data using modelling and visualizationData munging and manipulation is hard and statistics has just said that’s not our domain.”

* source : https://www.r-bloggers.com/hadley-wickham-on-why-he-created-all-those-r-packages/

 

 

Hadley Wickham의 Github repository 주소는요 https://github.com/hadley?tab=repositories  입니다. 여기 가보시면 엄청나게 많은 R packages들에 입이 쩍 벌어질겁니다. 만약에 노벨상에 R community에 기여한 공로를 치하하는 상으로 '노벨 R 상'이 있다면 Hadley Wickham이 그 첫번째 수상자가 된다고 해도 전혀 이상할게 없을 정도로 정말 R의 확산에 지대한 공헌을 하신 분입니다.

 

서론이 길었습니다.  ggplot2가 시각화/그래프에 관한한 우리를 실망시키지 않았듯이, dplyr 또한 데이터 전처리에 관한한 coverage의 방대함과 문법의 명료함이 우리를 매료시킬 것이라고 생각하며, 하나씩 예를 들어 설명을 시작해 보겠습니다.

 

아래의 설명은 browseVignettes(package = "dplyr") 치면 팝업으로 나오는 "Introduction to dplyr" HTML 페이지를 참조하였습니다.

 

예제로 사용할 데이터는 MASS 패키지에 들어있는 Cars93 데이터프레임입니다.  원래는 93개의 자동차 관측치에 27개의 변수를 가지고 있는데요, 예시들기 편하도록 앞에서부터 변수 8개만 선택해서 사용하겠습니다.  (Cars93_1 dataframe) 

 

> library(MASS)
> # subset Cars93
> Cars93_1 <- Cars93[, 1:8]
> str(Cars93_1)
'data.frame':	93 obs. of  8 variables:
 $ Manufacturer: Factor w/ 32 levels "Acura","Audi",..: 1 1 2 2 3 4 4 4 4 5 ...
 $ Model       : Factor w/ 93 levels "100","190E","240",..: 49 56 9 1 6 24 54 74 73 35 ...
 $ Type        : Factor w/ 6 levels "Compact","Large",..: 4 3 1 3 3 3 2 2 3 2 ...
 $ Min.Price   : num  12.9 29.2 25.9 30.8 23.7 14.2 19.9 22.6 26.3 33 ...
 $ Price       : num  15.9 33.9 29.1 37.7 30 15.7 20.8 23.7 26.3 34.7 ...
 $ Max.Price   : num  18.8 38.7 32.3 44.6 36.2 17.3 21.7 24.9 26.3 36.3 ...
 $ MPG.city    : int  25 18 20 19 22 22 19 16 19 16 ...
 $ MPG.highway : int  31 25 26 26 30 31 28 25 27 25 ...

 

 

 

 

단일 테이블을 대상으로 하는 dplyr 패키지의 함수들(Single table verbs)을 표로 정리해보면 아래와 같습니다.

 

 dplyr verbs

 description

 similar {package} function

 filter() 

 Filter rows with condition

 {base} subset

 slice()

 Filter rows with position

 {base} subset 

 arrange()

 Re-order or arrange rows

 {base} order

 select()

 Select columns

 {base} subset
 > select(df, starts_with())  Select columns that start with a prefix   
 > select(df, ends_with())  Select columns that end with a prefix  
 > select(df, contains())  Select columns that contain a character string  
 > select(df, matchs())  Select columns that match a regular expression  
 > select(df, one_of())  Select columns that are from a group of names  
 > select(df, num_range())  Select columns from num_range a to n with a prefix  

 rename()

 Rename column name

 {reshape} rename
 distinct()  Extract distinct(unique) rows  {base} unique
 sample_n()  Random sample rows for a fixed number  {base} sample
 sample_frac()  Random sample rows for a fixed fraction  {base} sample

 mutate()

 Create(add) new columns.
 mutate() allows you to refer to columns that you’ve just created.

 {base} transform 
 transmute()

 Create(add) new columns.

 transmute() only keeps the new columns.

 {base} transform

 summarise()

 Summarise values

 {base} summary

 

 

하나씩 설명을 이어가보면요,

 

(1) 데이터 프레임의 행 부분집합 선별 (select row subset from data frame) : filter(), slice()

 

 

(1-1) filter(dataframe, filter condition 1, filter condition 2, ...)

    : &(AND) 조건으로 row 데이터 부분집합 선별 (select a subset of rows in a data frame with 'AND' condition)

 

Cars93_1 데이터 프레임에 차종(Type)별로 보면 Compact 차종이 총 16개 있음을 알 수 있습니다. 

 

[문제] 차종(Type)이 "Compact"이면서 & 최대가격(Max.Price)이 20 백$ 이하이고 & 고속도로 연비(MPG.highway) 가 30 이상인 관측치를 선별하시오.

 

위 문제는 아래와 같이 dplyr의 filter() 함수를 사용하면 됩니다.  참고로, subset() 함수의 subset과 동일한 기능을 합니다.

 

> # number of cars by Type
> table(Cars93_1$Type)

Compact   Large Midsize   Small  Sporty     Van 
     16      11      22      21      14       9 
> 
> install.packages("dplyr")
> library(dplyr)
> # filter() : select a subset of rows in a data frame
> filter(Cars93_1, Type == c("Compact"), Max.Price <= 20, MPG.highway >= 30)
  Manufacturer    Model    Type Min.Price Price Max.Price MPG.city MPG.highway
1    Chevrolet Cavalier Compact       8.5  13.4      18.3       25          36
2    Chevrolet  Corsica Compact      11.4  11.4      11.4       25          34
3        Mazda      626 Compact      14.3  16.5      18.7       26          34
4       Nissan   Altima Compact      13.0  15.7      18.3       24          30
5   Oldsmobile  Achieva Compact      13.0  13.5      14.0       24          31
6      Pontiac  Sunbird Compact       9.4  11.1      12.8       23          31

 

 

 

 

(1-2) filter(dataframe, filter condition 1 | filter condition 2 | ...)

    : |(OR) 조건으로 row 데이터 부분집합 선별 (select a subset of rows in a data frame with 'OR' condition)

 

OR(또는) 조건으로 부분집합을 선별하려면 '|'를 사용하면 됩니다. (subset() 함수와 동일)

 

[문제] 차종(Type)이 "Compact"이거나 |(OR) 최대가격(Max.Price)이 20 백$ 이하이거나 |(OR) 고속도로 연비(MPG.highway) 가 30 이상인 관측치를 선별하시오.

 

위 문제는 래와 같이 dplyr의 filter() 함수를 사용하면 됩니다.  

 

> # filter(dataframe, condition1 | condition2) : or
> filter(Cars93_1, Type == c("Compact") | Max.Price <= 20 | MPG.highway >= 30)
    Manufacturer         Model    Type Min.Price Price Max.Price MPG.city MPG.highway
1          Acura       Integra   Small      12.9  15.9      18.8       25          31
2           Audi            90 Compact      25.9  29.1      32.3       20          26
3            BMW          535i Midsize      23.7  30.0      36.2       22          30
4          Buick       Century Midsize      14.2  15.7      17.3       22          31
5      Chevrolet      Cavalier Compact       8.5  13.4      18.3       25          36
6      Chevrolet       Corsica Compact      11.4  11.4      11.4       25          34
7      Chevrolet        Camaro  Sporty      13.4  15.1      16.8       19          28

     .....  이하 생략 (총 58개 관측치) ..... 

 

 

 

 

(1-3) slice(dataframe, from, to) : 위치를 지정해서 row 데이터 부분집합 선별하기 

 

filter()가 조건에 의한 선별이었다면, 위치(position)를 사용해서 부분집합 선별은 slice() 함수를 사용합니다.

 

[문제] Cars93_1 데이터프레임의 6번째에서 10번째 행(row)의 데이터를 선별하시오.

 

> # slice() : select rows by position
> slice(Cars93_1, 6:10)
  Manufacturer      Model    Type Min.Price Price Max.Price MPG.city MPG.highway
1        Buick    Century Midsize      14.2  15.7      17.3       22          31
2        Buick    LeSabre   Large      19.9  20.8      21.7       19          28
3        Buick Roadmaster   Large      22.6  23.7      24.9       16          25
4        Buick    Riviera Midsize      26.3  26.3      26.3       19          27
5     Cadillac    DeVille   Large      33.0  34.7      36.3       16          25

 

 

 

 

 (2) 데이터 프레임 행 정렬하기 (arrange rows of data frame) : arrange()

 

(2) arrange(dataframe, order criterion 1, order criterion 2, ...)

 

데이터 프레임을 정렬할 때 arrange() 함수를 쓰면 매우 편리합니다. 

여러개의 기준에 의해서 정렬을 하고 싶으면 기준 변수를 순서대로 나열하면 됩니다.

기본 정렬 옵셥은 오름차순(ascending)이며, 만약 내림차순(descending) 으로 정렬을 하고 싶다면 desc()를 입력해주면 됩니다.

 

[문제] 고속도로 연비(MPG.highway) 가 높은 순서대로 정렬을 하시오.  만약 고속도로 연비가 동일하다면 최고가격(Max.Price)가 낮은 순서대로 정렬하시오.  (난 연비가 높고 가격은 낮은 차가 좋아~)

 

> # arrange() : reorder rows of data frame
> arrange(Cars93_1, desc(MPG.highway), Max.Price)
    Manufacturer          Model    Type Min.Price Price Max.Price MPG.city MPG.highway
1            Geo          Metro   Small       6.7   8.4      10.0       46          50
2          Honda          Civic   Small       8.4  12.1      15.8       42          46
3         Suzuki          Swift   Small       7.3   8.6      10.0       39          43
4        Pontiac         LeMans   Small       8.2   9.0       9.9       31          41
5         Saturn             SL   Small       9.2  11.1      12.9       28          38
6          Mazda            323   Small       7.4   8.3       9.1       29          37
7         Subaru          Justy   Small       7.3   8.4       9.5       33          37
8         Toyota         Tercel   Small       7.8   9.8      11.8       32          37
9          Mazda        Protege   Small      10.9  11.6      12.3       28          36
10           Geo          Storm  Sporty      11.5  12.5      13.5       30          36

   .... 이하 생략 ....

 

 

 

 

참고로, arrange() 함수 말고도 아래처럼 order() 함수를 사용해서 indexing 하는 방법도 있습니다만, 아무래도 arrange() 함수가 더 깔끔하고 해석하기에 좋습니다.

 

> Cars93[order(-Cars93_1$MPG.highway, Cars93_1$Max.Price), ]
    Manufacturer          Model    Type Min.Price Price Max.Price MPG.city MPG.highway
39           Geo          Metro   Small       6.7   8.4      10.0       46          50
42         Honda          Civic   Small       8.4  12.1      15.8       42          46
83        Suzuki          Swift   Small       7.3   8.6      10.0       39          43
73       Pontiac         LeMans   Small       8.2   9.0       9.9       31          41
79        Saturn             SL   Small       9.2  11.1      12.9       28          38
53         Mazda            323   Small       7.4   8.3       9.1       29          37
80        Subaru          Justy   Small       7.3   8.4       9.5       33          37
84        Toyota         Tercel   Small       7.8   9.8      11.8       32          37
54         Mazda        Protege   Small      10.9  11.6      12.3       28          36
40           Geo          Storm  Sporty      11.5  12.5      13.5       30          36

 

 

 


 

(3) 데이터 프레임 변수 선별하기 : select()

 

(3-1) select(dataframe, VAR1, VAR2, ...) : 선별하고자 하는 변수 이름을 기입

 

[문제] Cars93_1 데이터 프레임으로부터 제조사명(Manufacturer), 최대가격(Max.Price), 고속도로연비(MPG.highway) 3개 변수(칼럼)를 선별하시오.

 

> # select() : Select columns by name
> select(Cars93_1, Manufacturer, Max.Price, MPG.highway)
    Manufacturer Max.Price MPG.highway
1          Acura      18.8          31
2          Acura      38.7          25
3           Audi      32.3          26
4           Audi      44.6          26
5            BMW      36.2          30

   .... 이하 생략 ....

 

 

 

 

(3-2) select(dataframe, VAR_a:VAR_n, ...) : a번째부터 n번째 변수 선별

 

서로 인접해서 줄지어서 있는 변수들을 선별하고자 할 때는 아래의 예시처럼 ':'를 사용하면 됩니다.

 

[문제] Cars93_1 데이터 프레임에서 1번째에 위치한 제조사(Manufacturer) ~ 5번째에 위치한 가격(Price)까지의 서로 이어저 있는 총 5개의 변수들을 선별하시오.

 

> select(Cars93_1, Manufacturer:Price)
    Manufacturer          Model    Type Min.Price Price
1          Acura        Integra   Small      12.9  15.9
2          Acura         Legend Midsize      29.2  33.9
3           Audi             90 Compact      25.9  29.1
4           Audi            100 Midsize      30.8  37.7
5            BMW           535i Midsize      23.7  30.0

     .... 이하 생략 ....

 

 

아래와 같이 서로 인접해서 줄지어서 있는 변수들의 위치를 알고 있으면 (가령 a부터 n번째 위치) 'a:n'처럼 숫자를 직접 입력해주면 바로 위의 결과와 동일한 결과를 얻을 수 있습니다.

 

> select(Cars93_1, 1:5)
    Manufacturer          Model    Type Min.Price Price
1          Acura        Integra   Small      12.9  15.9
2          Acura         Legend Midsize      29.2  33.9
3           Audi             90 Compact      25.9  29.1
4           Audi            100 Midsize      30.8  37.7
5            BMW           535i Midsize      23.7  30.0

     .... 이하 생략 ....

 

 

 

참고로, dplyr 패키지의 select() 함수는 base패키지에 내장되어 있는 subset(dataframe, select=...) 함수와 기능이 같습니다.  아래 subset() 함수 결과가 위와 동일합니다. (동일한 기능을 하는 함수가 여러개 있으니깐 헷갈리지요? ^^;)

 

> subset(Cars93_1, select = c(Manufacturer:Price))
    Manufacturer          Model    Type Min.Price Price
1          Acura        Integra   Small      12.9  15.9
2          Acura         Legend Midsize      29.2  33.9
3           Audi             90 Compact      25.9  29.1
4           Audi            100 Midsize      30.8  37.7
5            BMW           535i Midsize      23.7  30.0

   .... 이하 생략 .... 

 

 

 

 

(3-3) select(dataframe, -(VAR_a:VAR_n)) : a번째부터 n번째 변수는 쏙 빼고 선별

 

다시 dplyr 패키지로 돌아와서요, select() 함수에서 변수 앞에 '-'(minus) 부호를 사용하면 그 변수는 빼고(to drop variables) 선별하라는 뜻입니다.

 

> # select(dataframe, -var1, -var2, ...) : to drop variables
> select(Cars93_1, -(Manufacturer:Price)) Max.Price MPG.city MPG.highway 1 18.8 25 31 2 38.7 18 25 3 32.3 20 26 4 44.6 19 26 5 36.2 22 30

     .... 이하 생략 ....

 

 

 

 

(3-4) select(dataframe, starts_with("xx_name")) : "xx_name"으로 시작하는 모든 변수 선별

 

select() 함수 안에 starts_with() 를 사용해서 "xx_name"으로 시작하는 모든 변수를 선별할 수 있는 재미있는 기능도 가지고 있습니다.

 

[문제] Cars93_1 데이터 프레임에서 "MPG"로 시작하는 모든 변수를 선별하시오.

 

 

> # select(dataframe, starts_with("xx_name"))





> # : select all variables, starting with a "xx_name" prefix
> select(Cars93_1, starts_with("MPG"))
MPG.city MPG.highway 1 25 31 2 18 25 3 20 26 4 19 26 5 22 30
    .... 이하 생략 ....

 

"MPG"로 시작하는 변수가 "MPG.city"(도시 연비), "MPG.highway"(고속도로 연비) 두 개가 있군요.

 

 

 

 

(3-5) select(dataframe, ends_with("xx_name")) : "xx_name"으로 끝나는 모든 변수 선별

 

starts_with가() 있으면 ends_with()도 있지 않을까 싶지요?  네, 맞습니다.  "xx_name"으로 끝나는 모든 변수를 골라내고 싶다면 select() 함수 안에다가 ends_with() 를 추가해주면 됩니다.

 

[문제] Cars93_1 데이터 프레임에서 "Price"로 끝나는 모든 변수를 선별하시오.

 

> # select(dataframe, ends_with("xx_name"))
> #   : select all variables, ending with a "xx_name" prefix
> select(Cars93_1, ends_with("Price"))
   Min.Price Price Max.Price
1       12.9  15.9      18.8
2       29.2  33.9      38.7
3       25.9  29.1      32.3
4       30.8  37.7      44.6
5       23.7  30.0      36.2

    .... 이하 생략 .... 

 

"Price"로 끝나는 변수가 "Min.Price", "Price", "Max.Price" 총 3개가 있군요.

 

 

 

 

(3-6) select(dataframe, contains("xx_name")) : "xx_name"을 포함하는 모든 변수 선별

 

select() 함수에 contains() 를 사용하면 특정 이름을 포함하는 모든 변수를 선별할 수 있습니다. 이때 "xx_name"은 대소문자를 구분하지 않습니다.

 

[문제] Cars93_1 데이터 프레임에 있는 변수들 중에서 "P"를 포함하는 모든 변수를 선별하시오.

 

> # select(dataframe, contains("xx_string"))
> #   : select all variables which contains a "xx_string" literal string
> select(Cars93_1, contains("P"))
      Type Min.Price Price Max.Price MPG.city MPG.highway
1    Small      12.9  15.9      18.8       25          31
2  Midsize      29.2  33.9      38.7       18          25
3  Compact      25.9  29.1      32.3       20          26
4  Midsize      30.8  37.7      44.6       19          26
5  Midsize      23.7  30.0      36.2       22          30

   .... 이하 생략 ....

 

"P"를 포함하는 변수로는 "Type"(<- 이거는 소문자 'p'로서, 대소문자 구분 안함), "Min.Price", "Price", "Max.Price", "MPG.city", "MPG.highway"의 6개 변수가 있군요.

 

 

 

 

(3-7) select(dataframe, matches(".xx_string.")) : 정규 표현과 일치하는 문자열이 포함된 모든 변수 선별

 

역시 대소문자는 구분하지 않습니다.

 

[문제] 변수 문자열 중간에 "P"를 포함하는 변수를 모두 선별하시오

 

> # select(dataframe, matches(".xx_string."))
> #   : Select columns that match a regular expression
> head(select(Cars93_1, matches(".P.")))
     Type Min.Price Max.Price MPG.city MPG.highway
1   Small      12.9      18.8       25          31
2 Midsize      29.2      38.7       18          25
3 Compact      25.9      32.3       20          26
4 Midsize      30.8      44.6       19          26
5 Midsize      23.7      36.2       22          30
6 Midsize      14.2      17.3       22          31

 

> head(select(Cars93_1, matches("P"))) # exactly the same with contains("P")
     Type Min.Price Price Max.Price MPG.city MPG.highway
1   Small      12.9  15.9      18.8       25          31
2 Midsize      29.2  33.9      38.7       18          25
3 Compact      25.9  29.1      32.3       20          26
4 Midsize      30.8  37.7      44.6       19          26
5 Midsize      23.7  30.0      36.2       22          30
6 Midsize      14.2  15.7      17.3       22          31

 

위에 match() 옵션 안에다가 앞에 예제에는 (".P.")를, 뒤의 예제에는 점이 없이 ("P")를 사용했는데요, 그 결과를 보고 차이를 아시겠는지요?  앞뒤로 '.'(dot) 을 붙이면 시작과 끝 말고 변수명 중간에만 특정 문자열이 포함된 변수만 선별하라는 뜻입니다.  matches(".P.") 로 한 경우에는 "P"로 시작하는 "Price" 변수가 없는 반면에, 그냥 matches("P")로 한 경우는 "P"로 시작하는 "Price"변수가 포함되어 있습니다.

 

참고로, '.'(dot) 이 없이 matches()를 쓰면 contains() 와 동일한 결과를 반환합니다.

 

 

 

 

(3-8) select(dataframe, one_of(vars)) : 변수 이름 그룹에 포함된 모든 변수 선별

 

[문제] "Manufacturer", "MAX.Price", "MPG.highway" 의 3개 변수이름을 포함하는 변수 그룹이 있다고 할 때, Cars93 데이터 프레임에서 이 변수 그룹에 있는 변수가 있다면(<- 즉, 있을 수도 있지만 없을 수도 있다는 뜻임!) 모두 선별하시오.

 

> # select(dataframe, one_of(vars))
> #   : Select columns that are from a group of names
> vars <- c("Manufacturer", "MAX.Price", "MPG.highway")
> head(select(Cars93_1, one_of(vars)))
  Manufacturer MPG.highway
1        Acura          31
2        Acura          25
3         Audi          26
4         Audi          26
5          BMW          30
6        Buick          31
Warning message:
In one_of(vars) : Unknown variables: `MAX.Price`

 

 

위의 결과를 보니 "MAX.Price"라는 변수는 "Unknown variables"라고 해서 Warning mesage가 뜨는군요.  Cars93에 보면 "Max.Price"라는 변수는 있어도 "MAX.Price"라는 변수는 없거든요.  이처럼 변수 그룹 vars 에 나열된 이름 중에서 데이터 프레임에 포함된 변수는 선별해서 반환을 해주고, 만약 해당 이름의 변수가 없다면 그냥 Warning message를 제시해주는 것으로 잘 실행이 됩니다.

 

 

반면에 그냥 select() 함수로 위의 변수 그룹을 선별하라고 해보면요, 아래처럼  "object 'MAX.Price' not found" error 메시지와 함께 아예 실행이 안되요.  one_of() 함수가 어떤 때 쓰는건지 이제 이해하시겠지요?!

 

> select(Cars93_1, Manufacturer, MAX.Price, MPG.highway)
Error in eval(expr, envir, enclos) : object 'MAX.Price' not found

 

 

 

 

 

(3-9) select(dataframe, num_range("V", a:n)) : 접두사와 숫자 범위를 조합해서 변수 선별

 

변수 이름이 동일하게 특정 접두사로 시작하는 데이터 프레임의 경우 유용하게 사용할 수 있는 함수입니다.

 

[문제] "V1", "V2", "V3", "V4"의 4개 변수를 가진 df 데이터 프레임에서 "V2", "V3" 변수를 선별하시오. 단, 이때 접두사 "V"와 숫자 범위 2:3 을 조합해서 쓰는 num_range() 옵션을 사용하시오.

 

> # select(df, num_range("V", a:n))
> #   : Select columns from num_range a to n with a prefix
> V1 <- c(rep(1, 10))
> V2 <- c(rep(1:2, 5))
> V3 <- c(rep(1:5, 2))
> V4 <- c(rep(1:10))
> 
> df <- data.frame(V1, V2, V3, V4)
> df
   V1 V2 V3 V4
1   1  1  1  1
2   1  2  2  2
3   1  1  3  3
4   1  2  4  4
5   1  1  5  5
6   1  2  1  6
7   1  1  2  7
8   1  2  3  8
9   1  1  4  9
10  1  2  5 10
> 
> select(df, num_range("V", 2:3))
   V2 V3
1   1  1
2   2  2
3   1  3
4   2  4
5   1  5
6   2  1
7   1  2
8   2  3
9   1  4
10  2  5

 

 

 

 

 

 

(4) 데이터 프레임 변수 이름 변경하기 : rename()

 

dpylr 패키지의 rename() 함수는 rename(dataframe, new_var1 = old_var1, new_var2 = old_var2, ...) 의 형식으로 사용합니다. 

 

   - 새로운 변수 이름을 앞에, 이전 변수이름을 뒤에 위치시킵니다.

   - 큰 따옴표 안씁니다.  그냥 변수 이름만 쓰면 됩니다.

   - 이름을 변경하고자 하는 변수가 여러개 일 경우 ',' (comma)로 구분해서 연속해서 써줍니다.

 

 

[문제] Cars93_1 데이터 프레임의 8개 변수명 앞에 'New_' 라는 접두사(prefix)를 붙여서 변수 이름을 바꾸시오.

 

> # rename() : rename column name
> names(Cars93_1) 
[1] "Manufacturer" "Model"        "Type"         "Min.Price"    "Price"        "Max.Price"   
[7] "MPG.city"     "MPG.highway" 
> 

> # rename(dataframe, new_var1 = old_var1, new_var2 = old_var2, ...)
> Cars93_2 <- rename(Cars93_1,
+ New_Manufacturer = Manufacturer, + New_Model = Model, + New_Type = Type, + New_Min.Price = Min.Price, + New_Price = Price, + New_Max.Price = Max.Price, + New_MPG.city = MPG.city, + New_MPG.highway = MPG.highway) > > names(Cars93_2) [1] "New_Manufacturer" "New_Model" "New_Type" "New_Min.Price" [5] "New_Price" "New_Max.Price" "New_MPG.city" "New_MPG.highway"

 

 

 

이전에 plyr 패키지의 rename() 함수나 reshaple 패키지의 rename() 함수를 사용하던 분이라면 완전 헷갈리실 겁니다.  큰 따옴표("var_name")를 써야 하는건지 말아야 하는건지, 새로운 변수 이름(new_var)과 이전 변수 이름(old_var)의 위치가 앞인지 뒤인지, 변수가 여러개인 경우 c() 로 묶어주어야 하는지 아닌지가 패키지별로 조금씩 다르거든요. (참고  링크=> http://rfriend.tistory.com/41 ) 

 

저도 매번 헷갈립니다. -_-;  그래프는 ggplot2로 단일화해 나가듯이... 데이터 전처리는 dplyr 패키지로 단일화해 나가는 것도 헷갈림을 줄일 수 있는 좋은 전략이라고 생각합니다. (기존에 익혔던 함수가 아깝고 불편함을 못느낀다면 현상 유지도 물론 ok.)

 


dplyr 패키지의 distinct(), sample_n(), sample_frac(), mutate(), transmute(), summarise() 함수에 대해서는 다음번 포스팅에서 소개하겠습니다.

 

많은 도움이 되었기를 바랍니다.

 

이번 포스팅이 도움이 되었다면 아래의 '공감 ~ ♡'를 꾸욱 눌러주세요. ^^

 

 

 

 

 

728x90
반응형
Posted by Rfriend
,