[R] dplyr 패키지의 윈도우 함수 (2) Lead and Lag : lead() 함수, lag() 함수
R 분석과 프로그래밍/R 데이터 전처리 2016. 10. 22. 18:51window function은 n개의 행을 input으로 받아서 n개의 행을 가진 output을 반환하는 함수를 말합니다.
지난번 포스팅에서는 dplyr package의 window function 중에서 Ranking and Ordering을 하는 함수들로서 row_number(), min_rank(), dense_rank(), cume_dist(), percent_rank(), ntile() 에 대해서 알아보았습니다. (바로가기 http://rfriend.tistory.com/241)
이번 포스팅에서는 dplyr 패키지의 window function 두번째 시간으로서 특정 칼럼의 행을 위로 올리거나(Lead) 아니면 내리는(Lag) 함수에 대해서 알아보겠습니다.
lead() 나 lag() 함수는 시계열 데이터를 분석할 때 많이 사용하는 편입니다. 특정 그룹id와 날짜/시간 기준으로 정렬(sorting)을 해놓은 다음에, lead() 나 lag() 함수를 가지고 행을 하나씩 내리구요, 직전 날짜/시간 대비 이후의 값의 변화, 차이(difference)를 구하는 식으로 말이지요.
(시계열분석에 특화된 package를 사용하면 더 편하기 하지만.... 데이터 프레임을 가지고 dplyr 패키지의 lead()나 lag() 함수 알아놓는것도 유용해요)
먼저 간단한 벡터를 가지고 lead()와 lag() 사용법을 소개하겠습니다.
(1) lead(x, n = 1L, default = NA, ...) in {dplyr} package
lead() 함수는 벡터 값을 n = 1L (양의 정수값) 의 값 만큼 앞에서 제외하고, 제일 뒤의 n = 1L 값만큼의 값은 NA 로 채워놓은 값을 반환합니다. 이때, n 표기는 생략할 수 있습니다.
> ##------------------------------------------------- > ## R dplyr package : window function - lead and lag > ##------------------------------------------------- > > library(dplyr) > > # lead() > x <- c(1:10) > > lead(x, n = 1) [1] 2 3 4 5 6 7 8 9 10 NA > > lead(x, 2) [1] 3 4 5 6 7 8 9 10 NA NA
|
(2) lag(x, n = 1L, default = NA, ...) in {dplyr} package
lag() 함수는 lead() 함수와 정반대로 생각하시면 됩니다. lag() 함수의 n = 1L(양의 정수값) 만큼 제일 앞자리부터 뒤로 옮기고, n = 1L 개수 만큼의 자리에 NA 값을 채워넣은 값을 반환합니다.
default = "." 처럼 특정 값을 설정해주면 NA 대신 새로 설정해준 값 혹은 기호가 채워진 값을 반환합니다. (아래 세번째 예의 경우 "."으로 빈 자리가 채워지면서 모든 값에 큰 따옴표("")가 붙으면서 character 형태로 바뀌었습니다)
> # lag() > x <- c(1:10) > > lag(x, n = 1) [1] NA 1 2 3 4 5 6 7 8 9 > > lag(x, 2) [1] NA NA 1 2 3 4 5 6 7 8 > > lag(x, 2, default = ".") [1] "." "." "1" "2" "3" "4" "5" "6" "7" "8"
|
[문제] 위의 x_df 데이터 프레임의 group 별로 직전 대비 직후 값의 차이가 가장 큰 값(max)과 가장 작은 값을 각각 구하시오. (What are the max and min difference values between x and lag(x) of x_df dataframe by group?)
(0) 예제 데이터 프레임 만들기
분석할 때 보통 벡터 보다는 데이터 프레임을 가지고 많이 하므로 예제 데이터 프레임을 하나 만들어보겠습니다. 'group'이라는 요인(factor)형 변수와 seq_no 이라는 시간 순서를 나타내는 변수, 그리고 각 group별로 5개씩의 관찰값을 가진 숫자형(numeric) 변수 x로 구성된 데이터 프레임입니다.
> ##-- make data frame as an example > group <- rep(c("A", "B"), each = 5) > seq_no <- rep(1:5, 2) > set.seed(1234) > x <- round(100*runif(10), 1) > > x_df <- data.frame(group, seq_no, x) > x_df group seq_no x 1 A 1 11.4 2 A 2 62.2 3 A 3 60.9 4 A 4 62.3 5 A 5 86.1 6 B 1 64.0 7 B 2 0.9 8 B 3 23.3 9 B 4 66.6 10 B 5 51.4
|
(1) lag() 하려고 하는 기준대로 정렬이 안되어 있으면 -> 먼저 정렬(sorting) 부터!
예제로 사용하려고 sample(nrow()) 함수로 무작위로 순서를 섞어서 x_df_random 이라는 데이터 프레임을 만들어보았습니다. dplyr 패키지의 arrange() 함수를 가지고 group, seq_no 기준으로 정렬을 해보겠습니다.
> # if data frame is not ordered properly, > # then arrnage it first by lag criteria > x_df_random <- x_df[sample(nrow(x_df)),] > x_df_random group seq_no x 7 B 2 0.9 5 A 5 86.1 3 A 3 60.9 10 B 5 51.4 2 A 2 62.2 9 B 4 66.6 6 B 1 64.0 1 A 1 11.4 8 B 3 23.3 4 A 4 62.3 > > x_df_seq <- arrange(x_df_random, group, seq_no) > x_df_seq group seq_no x 1 A 1 11.4 2 A 2 62.2 3 A 3 60.9 4 A 4 62.3 5 A 5 86.1 6 B 1 64.0 7 B 2 0.9 8 B 3 23.3 9 B 4 66.6 10 B 5 51.4
|
(2) mutate() 함수와 lag() 함수로 group_x, x_lag 변수 만들기
|
(3) group 과 group_lag 의 값이 서로 다르면 그 행(row)은 filter() 함수로 제외하기
> # if group and group_lag are different, then delete the row > x_df_seq_lag_2 <- x_df_seq_lag %>% + filter(group == group_lag) > > x_df_seq_lag_2 group seq_no x group_lag x_lag 1 A 2 62.2 A 11.4 2 A 3 60.9 A 62.2 3 A 4 62.3 A 60.9 4 A 5 86.1 A 62.3 5 B 2 0.9 B 64.0 6 B 3 23.3 B 0.9 7 B 4 66.6 B 23.3 8 B 5 51.4 B 66.6
|
(4) group별로 x와 x_lag 값의 차이가 가장 큰 값(max)과 가장 작은 값(min) 구하기
지지난번 포스팅에서 소개했던 group_by()와 summarise(max()), summarise(min()) 함수를 이용하면 되겠습니다.
> # select max and min of difference between x and x_lag > x_df_seq_lag_2 %>% + group_by(group) %>% + summarise(max_lag = max(x - x_lag, na.rm = TRUE), + min_lag = min(x - x_lag, na.rm = TRUE)) # A tibble: 2 x 3 group max_lag min_lag <fctr> <dbl> <dbl> 1 A 50.8 -1.3 2 B 43.3 -63.1
|
(5) 위의 1~4를 chain operator와 group_by() 를 사용해서 한번에 모두 처리하기.
library(dplyr) ## sample data group <- rep(c("A", "B"), each = 5) seq_no <- rep(1:5, 2) set.seed(1234) x <- round(100*runif(10), 1) x_df <- data.frame(group, seq_no, x) ## max and min of (x - x_lag) x_df %>% arrange(group, seq_no) %>% group_by(group) %>% summarise(max_lag = max(x - lag(x, 1), na.rm = TRUE), min_lag = min(x - lag(x, 1), na.rm = TRUE)) # # A tibble: 2 x 3 # group max_lag min_lag # <chr> <dbl> <dbl> # 1 A 50.8 -1.3 # 2 B 43.3 -63.1
|
그리 어렵지 않지요?
많은 도움이 되었기를 바랍니다.
다음번 포스팅에서는 dplry package window function 세번째로 시간으로 Cumulative aggregates 를 하는데 사용하는 cumall(), cumany(), cummean() 함수, 그리고 Recycled aggregates 에 대해서 알아보겠습니다.
이번 포스팅이 도움이 되었다면 아래의 '공감 ~♡'를 눌러주세요.
(Tistory 가 포스팅별로 조회수를 알려주는 기능이 없다보니 '공감♡' 개수로 참고하려고해요)