Tidyvers 소개

ggplot의 개발자인 Hadley Wickam의 Tidyverse패키지안에
dplyr, tidyr, tidytext, ggplot2, readr들이 다 포함되어있다.

  1. tidyverse : 포함된 패키지들 모두에서 pipe operator를 사용할 수 있다.

    • %>%를 사용하여 가독성 및 naming이 필요없어진다. 마치 ggplot의 + 연산자와 똑같음
  2. readr : read_csv()을 사용할 수 있어
    1) read.csv()보다 더 빠르다( string을 factor로 자동변환이 없음 )
    2) data.frame대신 tibble을 사용하여 최종적으로는 4~5배 빠르다고 한다.
    3) cf) data.table 패키지는 100배 이상 빠르게 사용할 수 있다고 한다.


Dplyr

가장 큰 특징 2가지는 pipe linegroup별 계산인데, 세부적으로 아래와 같다.

  1. select() : 쉽게 필요한 칼럼만 인덱싱 or 새로운칼럼명 = 으로 칼럼명 변경

    • select( data, 칼럼명)
    • select( data, c()없이 여러개 칼럼명 연결, 1, 2, 3)
    • select( data, starts_wwith("칼럼명 시작단어 선택")
    • select( data, ends_wwith("칼럼명 끝단어 선택")
    • select( data, contains("포함 단어 선택")
    • select( data, 새로운칼럼명 = 뽑아낸 칼럼 )
  2. filter() : 쉽게 필요한 행(특정범주)만 인덱싱

    • filter( data, 칼럼명 조건 )
    • filter( data, 칼럼명 조건 & 칼럼명2 조건2 )
  3. arrange() : 쉽게 오름/내림차순 정렬

    • arrange( data, 오름차순 정렬기준칼럼명 )
    • arrange( data, desc(오름차순 정렬기준칼럼명) )
  4. mutate() : 쉽게 새로운 칼럼 생성 by 기존칼럼를 변형

    • mutate( data, 새로운칼럼명 = 기존칼럼명 + 수식 )
  5. group_by() & Summarise() : 그룹별 통계량

    • filter()로 필요행(특정범주)인덱싱 후 summarise( filtedData, mean(칼럼명, na.rm=T)
    • filter() -> group_by( filterdData, 기준칼럼명 ) -> summarise( groupedData, 통계함수 ) 그룹별 통계
  6. %>% : 파이프라인

    • data %>% filter( 칼럼명과 조건) %>% group_by( 기준칼럼명 ) %>% summarise( 집계함수))
    • 각 함수에서 data부분만 생략됨
  7. 그외 count, sample


Tidyr으로 데이터 reshape

  1. spread() : to wide
  2. gather() : to long

R markdown

Untitled

Dplyr

  • dplyr has 5 verbs which make up the majority of the data manipulation tasks we perform.
  • 1.Select: used to select one or more columns;
  • 2.Filter: used to select some rows based on specific criteria;
  • 3.Arrange: used to sort data based on one or more columns in ascending or descending order;
  • 4.Mutate: used to add new columns to our data;
  • 5.Summarise: used to create chunks(묶음) from our data.

파이프라인 및 전체 연습

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(moonBook)

#### 파이프라인 없이 해보기
# 1. filter()로 행인덱싱(특정범주 가져오기)
acs2 <- filter( acs, sex == "Female" & age > 40)
# 2. arrange()로 내림차순 정렬
ordered_acs2 <- arrange( acs2, desc(height))
# 3. group_by()로 그룹화 -> tibble로 변형 & 그룹화를 직접적으로 하진 않음
obesity_to_acs2 <- group_by(ordered_acs2, obesity)
head(obesity_to_acs2) # tibble상에서는 그룹화 안되어있음. 그룹별 집계가 가능한 상태만 Groups로 표시
## # A tibble: 6 x 17
## # Groups:   obesity [2]
##     age sex   cardiogenicShock entry Dx       EF height weight   BMI
##   <int> <chr> <chr>            <chr> <chr> <dbl>  <dbl>  <dbl> <dbl>
## 1    67 Fema~ No               Radi~ Unst~  57.2    168     52  18.4
## 2    89 Fema~ No               Femo~ STEMI  21.8    165     50  18.4
## 3    64 Fema~ No               Radi~ Unst~  57.7    165     74  27.2
## 4    53 Fema~ No               Radi~ Unst~  58.4    165     75  27.5
## 5    64 Fema~ No               Radi~ STEMI  59      165     71  26.1
## 6    48 Fema~ No               Radi~ STEMI  61.5    165     58  21.3
## # ... with 8 more variables: obesity <chr>, TC <dbl>, LDLC <int>,
## #   HDLC <int>, TG <int>, DM <chr>, HBP <chr>, smoking <chr>
# 4. summarise()로 그룹별 집계
obesity_to_BMI_mean <- summarise(obesity_to_acs2, mean( BMI, na.rm = T))


#### 파이프라인을 통해 naming걱정없이 바로 해보기
acs %>%
  filter( sex == "Female" & age > 40) %>%
  arrange( desc(height))  %>%
  group_by( obesity ) %>%
  summarise( mean( BMI, na.rm = T))
## # A tibble: 2 x 2
##   obesity `mean(BMI, na.rm = T)`
##   <chr>                    <dbl>
## 1 No                        22.2
## 2 Yes                       27.7

select() : 필료한 칼럼인덱싱 & 칼럼명 변경도 가느

library(dplyr)
head(iris) # 내장 데이터
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2  setosa
## 2          4.9         3.0          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2  setosa
## 5          5.0         3.6          1.4         0.2  setosa
## 6          5.4         3.9          1.7         0.4  setosa
# select() - 필요한 칼럼만 인덱싱
head( select( iris, Sepal.Length) )
##   Sepal.Length
## 1          5.1
## 2          4.9
## 3          4.7
## 4          4.6
## 5          5.0
## 6          5.4
head( select( iris, Sepal.Length, Sepal.Width) )
##   Sepal.Length Sepal.Width
## 1          5.1         3.5
## 2          4.9         3.0
## 3          4.7         3.2
## 4          4.6         3.1
## 5          5.0         3.6
## 6          5.4         3.9
# select() - 특정조건의 칼럼명 뽑아내기
head( select( iris, starts_with( "Sepal")) ) # Sepal 로 시작하는 칼럼명만인덱싱
##   Sepal.Length Sepal.Width
## 1          5.1         3.5
## 2          4.9         3.0
## 3          4.7         3.2
## 4          4.6         3.1
## 5          5.0         3.6
## 6          5.4         3.9
head( select( iris, ends_with( "Width")) )
##   Sepal.Width Petal.Width
## 1         3.5         0.2
## 2         3.0         0.2
## 3         3.2         0.2
## 4         3.1         0.2
## 5         3.6         0.2
## 6         3.9         0.4
head( select( iris, contains( "etal")) ) # contain아님 contains
##   Petal.Length Petal.Width
## 1          1.4         0.2
## 2          1.4         0.2
## 3          1.3         0.2
## 4          1.5         0.2
## 5          1.4         0.2
## 6          1.7         0.4
# select() - 칼럼명 변경해서 인덱싱
head( select( iris, petal = Petal.Length) )
##   petal
## 1   1.4
## 2   1.4
## 3   1.3
## 4   1.5
## 5   1.4
## 6   1.7
head( select( iris, petal = starts_with("Petal")) ) # 인덱싱 칼럼 2개를 하나의 칼럼명에 넣으면 뒤에 숫자 1, 2 붙어서 칼럼명 생성 ex> petal1, petal2
##   petal1 petal2
## 1    1.4    0.2
## 2    1.4    0.2
## 3    1.3    0.2
## 4    1.5    0.2
## 5    1.4    0.2
## 6    1.7    0.4

filter() - 행인덱싱, 특정범주 인덱싱

head(airquality)
##   Ozone Solar.R Wind Temp Month Day
## 1    41     190  7.4   67     5   1
## 2    36     118  8.0   72     5   2
## 3    12     149 12.6   74     5   3
## 4    18     313 11.5   62     5   4
## 5    NA      NA 14.3   56     5   5
## 6    28      NA 14.9   66     5   6
head( filter( airquality, Temp > 70) )
##   Ozone Solar.R Wind Temp Month Day
## 1    36     118  8.0   72     5   2
## 2    12     149 12.6   74     5   3
## 3     7      NA  6.9   74     5  11
## 4    11     320 16.6   73     5  22
## 5    45     252 14.9   81     5  29
## 6   115     223  5.7   79     5  30
head( filter( airquality, Temp > 70 & Month > 5) )
##   Ozone Solar.R Wind Temp Month Day
## 1    NA     286  8.6   78     6   1
## 2    NA     287  9.7   74     6   2
## 3    NA     186  9.2   84     6   4
## 4    NA     220  8.6   85     6   5
## 5    NA     264 14.3   79     6   6
## 6    29     127  9.7   82     6   7

arrange()

# default는 오름차순
head( arrange( airquality, Ozone) )
##   Ozone Solar.R Wind Temp Month Day
## 1     1       8  9.7   59     5  21
## 2     4      25  9.7   61     5  23
## 3     6      78 18.4   57     5  18
## 4     7      NA  6.9   74     5  11
## 5     7      48 14.3   80     7  15
## 6     7      49 10.3   69     9  24
# desc(기준칼럼명) 내림차순
head( arrange( airquality, desc(Ozone)) )
##   Ozone Solar.R Wind Temp Month Day
## 1   168     238  3.4   81     8  25
## 2   135     269  4.1   84     7   1
## 3   122     255  4.0   89     8   7
## 4   118     225  2.3   94     8  29
## 5   115     223  5.7   79     5  30
## 6   110     207  8.0   90     8   9
# 기준을 2개로
head( arrange( airquality, desc(Ozone), Day) )
##   Ozone Solar.R Wind Temp Month Day
## 1   168     238  3.4   81     8  25
## 2   135     269  4.1   84     7   1
## 3   122     255  4.0   89     8   7
## 4   118     225  2.3   94     8  29
## 5   115     223  5.7   79     5  30
## 6   110     207  8.0   90     8   9

mutate() - 기존칼럼 + 수식으로 새로운 칼럼 생성(한 df return)

head( mutate( airquality, TempInc = (Temp - 32) * 5 / 9) )
##   Ozone Solar.R Wind Temp Month Day  TempInc
## 1    41     190  7.4   67     5   1 19.44444
## 2    36     118  8.0   72     5   2 22.22222
## 3    12     149 12.6   74     5   3 23.33333
## 4    18     313 11.5   62     5   4 16.66667
## 5    NA      NA 14.3   56     5   5 13.33333
## 6    28      NA 14.9   66     5   6 18.88889

summarise() with group_by()

# group_by()안하더라도, 집계한다.
summarise(airquality, mean(Temp, na.rm = T))
##   mean(Temp, na.rm = T)
## 1              77.88235
# group_by()와 함께
summarise(group_by(airquality, Month), mean(Temp, na.rm = T))
## # A tibble: 5 x 2
##   Month `mean(Temp, na.rm = T)`
##   <int>                   <dbl>
## 1     5                    65.5
## 2     6                    79.1
## 3     7                    83.9
## 4     8                    84.0
## 5     9                    76.9

연습해보기

  • COPD데이터에서 성별 남자만 추출 -> 흡연이력으로 group_by()후 BMI의 평균을 summarise
library(moonBook)
data(acs)
head(acs)
##   age    sex cardiogenicShock   entry              Dx   EF height weight
## 1  62   Male               No Femoral           STEMI 18.0    168     72
## 2  78 Female               No Femoral           STEMI 18.4    148     48
## 3  76 Female              Yes Femoral           STEMI 20.0     NA     NA
## 4  89 Female               No Femoral           STEMI 21.8    165     50
## 5  56   Male               No  Radial          NSTEMI 21.8    162     64
## 6  73 Female               No  Radial Unstable Angina 22.0    153     59
##        BMI obesity  TC LDLC HDLC  TG  DM HBP smoking
## 1 25.51020     Yes 215  154   35 155 Yes  No  Smoker
## 2 21.91381      No  NA   NA   NA 166  No Yes   Never
## 3       NA      No  NA   NA   NA  NA  No Yes   Never
## 4 18.36547      No 121   73   20  89  No  No   Never
## 5 24.38653      No 195  151   36  63 Yes Yes  Smoker
## 6 25.20398     Yes 184  112   38 137 Yes Yes   Never
acs %>%
  filter( sex == "Male") %>%
  group_by( smoking ) %>%
  summarise( mean(BMI, na.rm = T))
## # A tibble: 3 x 2
##   smoking   `mean(BMI, na.rm = T)`
##   <chr>                      <dbl>
## 1 Ex-smoker                   24.5
## 2 Never                       24.4
## 3 Smoker                      24.2

+ Recent posts