[참고] https://www.r-bloggers.com/lesser-known-dplyr-functions/
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 패턴과 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)
***