[참고] https://www.r-bloggers.com/lesser-known-dplyr-functions/


tidyr

dplyr


library(tidyverse)
library(EDAWR)
library(gapminder)

data(storms)
head(storms)
##     storm wind pressure       date
## 1 Alberto  110     1007 2000-08-03
## 2    Alex   45     1009 1998-07-27
## 3 Allison   65     1005 1995-06-03
## 4     Ana   40     1013 1997-06-30
## 5  Arlene   50     1010 1999-06-11
## 6  Arthur   45     1010 1996-06-17
# 유용한 select() 내장 함수

# - 해당 변수를 제외한 모든 칼럼을 선택한다.
# : 해당 범위에 해당되는 칼럼을 선택한다.
# contains()    해당 문자열을 명칭을 포함한 칼럼을 선택한다.
# starts_with() 해당 문자열로 시작하는 명칭을 포함한 칼럼을 선택한다.
# ends_with()   해당 문자열로 끝나는 명칭을 포함한 칼럼을 선택한다.
# everything()  모든 칼럼을 선택한다.
# matches() 정규표현식을 매칭하는 칼럼을 선택한다.
# num_range()   x1, x2, x3, x4, x5 명칭이 붙은 칼럼을 선택한다.
# one_of()  그룹에 명칭이 담긴 칼럼을 선택한다.

# 변수 select 동사
storms %>% select(wind, pressure)
##   wind pressure
## 1  110     1007
## 2   45     1009
## 3   65     1005
## 4   40     1013
## 5   50     1010
## 6   45     1010
storms %>% select(-wind)
##     storm pressure       date
## 1 Alberto     1007 2000-08-03
## 2    Alex     1009 1998-07-27
## 3 Allison     1005 1995-06-03
## 4     Ana     1013 1997-06-30
## 5  Arlene     1010 1999-06-11
## 6  Arthur     1010 1996-06-17
select(storms, wind:date)
##   wind pressure       date
## 1  110     1007 2000-08-03
## 2   45     1009 1998-07-27
## 3   65     1005 1995-06-03
## 4   40     1013 1997-06-30
## 5   50     1010 1999-06-11
## 6   45     1010 1996-06-17

# filter() R 논리 연산자

# < 적다  &   그리고
# > 크다  |   또는
# ==    같다  xor 배타적 논리합
# <=    이하  !   부정
# >=    이상  any 참이 있음
# !=    같지 않다   all 모두 참
# %in%  포함한다        
# is.na NA 값이다      
# !is.na    NA 값이 아니다.  

# 관측점 filter 동사
filter(storms, wind >= 50)
##     storm wind pressure       date
## 1 Alberto  110     1007 2000-08-03
## 2 Allison   65     1005 1995-06-03
## 3  Arlene   50     1010 1999-06-11
filter(storms, wind >= 50, storm %in% c("Alberto", "Alex", "Allison"))
##     storm wind pressure       date
## 1 Alberto  110     1007 2000-08-03
## 2 Allison   65     1005 1995-06-03

# 유용한 mutate() 내장 함수

# pmin(), pmax()    관측점별 최소값, 최대값
# cummin(), cummax()    누적 최소값, 최대값
# cumsum(), cumprod()   누적합, 누적곱
# between() a와 b 사이
# cume_dist()   누적 분포값
# cumall(), cumany()    모든 누적값, 조건이 맞는 누적값
# cummean() 누적 평균
# lead(), lag() 위치 값을 선행 혹은 후행하여 복사
# ntile()   벡터를 n개 구간을 분할
# dense_rank(), min_rank(),, percent_rank(), row_number()   다양한 순위 방법

# 변수 생성 mutate 동사
mutate(storms, ratio = pressure / wind)
##     storm wind pressure       date     ratio
## 1 Alberto  110     1007 2000-08-03  9.154545
## 2    Alex   45     1009 1998-07-27 22.422222
## 3 Allison   65     1005 1995-06-03 15.461538
## 4     Ana   40     1013 1997-06-30 25.325000
## 5  Arlene   50     1010 1999-06-11 20.200000
## 6  Arthur   45     1010 1996-06-17 22.444444
mutate(storms, ratio = pressure / wind, inverse = ratio^-1)
##     storm wind pressure       date     ratio    inverse
## 1 Alberto  110     1007 2000-08-03  9.154545 0.10923535
## 2    Alex   45     1009 1998-07-27 22.422222 0.04459861
## 3 Allison   65     1005 1995-06-03 15.461538 0.06467662
## 4     Ana   40     1013 1997-06-30 25.325000 0.03948667
## 5  Arlene   50     1010 1999-06-11 20.200000 0.04950495
## 6  Arthur   45     1010 1996-06-17 22.444444 0.04455446

# 유용한 summarize() 내장 함수

# min(), max()  최소값, 최대값
# mean()    평균
# median()  중위수
# sum() 합계
# var, sd() 분산, 표준편차
# first()   첫번째 값
# last()    마지막 값
# nth() n번째 값
# n()   해당 벡터에 값 개수
# n_distinct()  해당 벡터에 유일무이한 값 개수

# 분석단위 변경(요약) summerise 동사
data(pollution) # library(emmeans)
pollution %>% 
  summarise(median = median(amount), variance = var(amount))
##   median variance
## 1   22.5   1731.6
pollution %>% 
  summarise(mean = mean(amount), sum = sum(amount), n = n())
##   mean sum n
## 1   42 252 6

# 정렬 arrange 동사
arrange(storms, wind)
##     storm wind pressure       date
## 1     Ana   40     1013 1997-06-30
## 2    Alex   45     1009 1998-07-27
## 3  Arthur   45     1010 1996-06-17
## 4  Arlene   50     1010 1999-06-11
## 5 Allison   65     1005 1995-06-03
## 6 Alberto  110     1007 2000-08-03
arrange(storms, desc(wind))
##     storm wind pressure       date
## 1 Alberto  110     1007 2000-08-03
## 2 Allison   65     1005 1995-06-03
## 3  Arlene   50     1010 1999-06-11
## 4    Alex   45     1009 1998-07-27
## 5  Arthur   45     1010 1996-06-17
## 6     Ana   40     1013 1997-06-30
arrange(storms, wind, date)
##     storm wind pressure       date
## 1     Ana   40     1013 1997-06-30
## 2  Arthur   45     1010 1996-06-17
## 3    Alex   45     1009 1998-07-27
## 4  Arlene   50     1010 1999-06-11
## 5 Allison   65     1005 1995-06-03
## 6 Alberto  110     1007 2000-08-03
# (분석 단위) group_by() 함수 동사

pollution %>% group_by(city) %>%
  summarise(mean = mean(amount), sum = sum(amount), n = n()) %>% 
  ungroup()
## # A tibble: 3 x 4
##   city      mean   sum     n
##   <chr>    <dbl> <dbl> <int>
## 1 Beijing   88.5   177     2
## 2 London    19      38     2
## 3 New York  18.5    37     2

dplyr 동사와 Base 구문 비교


# dplyr 패턴과 transmute 동사
# group_by + mutate: 그룹별 비율
# group_by() 동사와 mutate()를 적용시킨 패턴도 많이 사용하는 패턴이다.
# 예를 들어, gapminder 데이터셋의 가장 최근 2007년 기준 각 대륙별 인구를 모두 더해서 total_pop를 계산하고 나서 각 대륙별로 가장 인구가 많은 국가와 가장 점유율이 높은 국가를 뽑아낼 수 있다. 먼저 각 대륙별 가장 인구가 많은 국가를 1곳 뽑아보자

gapminder %>% 
  mutate(pop = pop / 100000000) %>% # 단위 억명
  filter(year == max(year)) %>% 
  group_by(continent) %>% 
  mutate(total_pop = sum(pop)) %>% 
  top_n(1, wt=pop)
## # A tibble: 5 x 7
## # Groups:   continent [5]
##   country       continent  year lifeExp    pop gdpPercap total_pop
##   <fct>         <fct>     <int>   <dbl>  <dbl>     <dbl>     <dbl>
## 1 Australia     Oceania    2007    81.2  0.204    34435.     0.245
## 2 China         Asia       2007    73.0 13.2       4959.    38.1  
## 3 Germany       Europe     2007    79.4  0.824    32170.     5.86 
## 4 Nigeria       Africa     2007    46.9  1.35      2014.     9.30 
## 5 United States Americas   2007    78.2  3.01     42952.     8.99
gapminder %>% 
  mutate(pop = pop / 100000000) %>% # 단위 억명
  filter(year == max(year)) %>% 
  group_by(continent) %>% 
  mutate(total_pop = sum(pop),
         fraction = pop / total_pop) %>% 
  top_n(1, wt=fraction)
## # A tibble: 5 x 8
## # Groups:   continent [5]
##   country       continent  year lifeExp    pop gdpPercap total_pop fraction
##   <fct>         <fct>     <int>   <dbl>  <dbl>     <dbl>     <dbl>    <dbl>
## 1 Australia     Oceania    2007    81.2  0.204    34435.     0.245    0.832
## 2 China         Asia       2007    73.0 13.2       4959.    38.1      0.346
## 3 Germany       Europe     2007    79.4  0.824    32170.     5.86     0.141
## 4 Nigeria       Africa     2007    46.9  1.35      2014.     9.30     0.145
## 5 United States Americas   2007    78.2  3.01     42952.     8.99     0.335

# group_by + 윈도우 함수: 그룹별 변화율
# group_by() 동사와 윈도우 함수(lag, lead 등)를 사용해서 년도별 변화가 가장 큰 특징점을 뽑아낼 수 있다. 이를 통해서 가장 인구가 많이 줄어든 시점과 국가를 쉽게 특정할 수 있다.

gapminder_window <- gapminder %>% 
  group_by(continent, country) %>% 
  arrange(continent, country, year) %>% 
  mutate(lifeExp_lag = lag(lifeExp)) %>% 
  mutate(difference = lifeExp - lifeExp_lag) %>% 
  select(country, continent, year, lifeExp, lifeExp_lag, difference) %>% 
  ungroup()

worst_countries <- gapminder_window %>% 
  top_n(5, wt=-difference) %>% 
  pull(country)

gapminder_window %>% 
  filter(country %in% worst_countries) %>% 
  arrange(difference)
## # A tibble: 60 x 6
##    country   continent  year lifeExp lifeExp_lag difference
##    <fct>     <fct>     <int>   <dbl>       <dbl>      <dbl>
##  1 Rwanda    Africa     1992    23.6        44.0     -20.4 
##  2 Zimbabwe  Africa     1997    46.8        60.4     -13.6 
##  3 Lesotho   Africa     2002    44.6        55.6     -11.0 
##  4 Swaziland Africa     2002    43.9        54.3     -10.4 
##  5 Botswana  Africa     1997    52.6        62.7     -10.2 
##  6 Zimbabwe  Africa     2002    40.0        46.8      -6.82
##  7 Botswana  Africa     2002    46.6        52.6      -5.92
##  8 Swaziland Africa     2007    39.6        43.9      -4.26
##  9 Swaziland Africa     1997    54.3        58.5      -4.18
## 10 Lesotho   Africa     1997    55.6        59.7      -4.13
## # ... with 50 more rows

# transmute 동사
# transmute 동사는 select와 mutate를 결합한 동사로 코드를 좀더 간결하게 만들 수 있다. 예를 들어, GDP를 계산하는데 인구(pop)와 일인당 GDP(gdpPercap)을 곱해야 계산할 수 있는데, mutate + select를 동원하면 코드가 길어지는데 transmute를 사용하면 한줄로 깔끔하게 구할 수 있다.

gapminder %>% 
  mutate(GDP = pop * gdpPercap) %>% 
  select(continent, country, GDP)
## # A tibble: 1,704 x 3
##    continent country              GDP
##    <fct>     <fct>              <dbl>
##  1 Asia      Afghanistan  6567086330.
##  2 Asia      Afghanistan  7585448670.
##  3 Asia      Afghanistan  8758855797.
##  4 Asia      Afghanistan  9648014150.
##  5 Asia      Afghanistan  9678553274.
##  6 Asia      Afghanistan 11697659231.
##  7 Asia      Afghanistan 12598563401.
##  8 Asia      Afghanistan 11820990309.
##  9 Asia      Afghanistan 10595901589.
## 10 Asia      Afghanistan 14121995875.
## # ... with 1,694 more rows
gapminder %>% 
  transmute(continent, country, GDP = pop * gdpPercap)
## # A tibble: 1,704 x 3
##    continent country              GDP
##    <fct>     <fct>              <dbl>
##  1 Asia      Afghanistan  6567086330.
##  2 Asia      Afghanistan  7585448670.
##  3 Asia      Afghanistan  8758855797.
##  4 Asia      Afghanistan  9648014150.
##  5 Asia      Afghanistan  9678553274.
##  6 Asia      Afghanistan 11697659231.
##  7 Asia      Afghanistan 12598563401.
##  8 Asia      Afghanistan 11820990309.
##  9 Asia      Afghanistan 10595901589.
## 10 Asia      Afghanistan 14121995875.
## # ... with 1,694 more rows

DT::datatable(cases)
DT::datatable(pollution)

***