Сгруппируйте по нескольким столбцам и рассчитайте годовые и ежемесячные процентные изменения в R

#r #dataframe #dplyr

#r #фрейм данных #dplyr

Вопрос:

Учитывая df фрейм данных следующим образом:

 df <- structure(list(city = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L), .Label = "bj", class = "factor"), id = c(1010082465L, 
1010082465L, 1010082465L, 1010082465L, 1010082465L, 1010082465L, 
1010082465L, 1010082465L, 1010082465L, 1010082465L, 1010082465L, 
1010082465L, 1010082465L, 1010082465L, 1010082465L, 1010082465L, 
1010082465L, 1010082465L, 1010082465L, 1010103000L, 1010103000L, 
1010103000L, 1010103000L, 1010103000L, 1010103000L, 1010103000L, 
1010103000L, 1010103000L, 1010103000L, 1010103000L, 1010103000L, 
1010103000L, 1010103000L, 1010103000L, 1010103000L, 1010103000L, 
1010103000L, 1010103000L, 1010084621L, 1010084621L, 1010084621L, 
1010084621L, 1010084621L, 1010084621L, 1010084621L, 1010084621L, 
1010084621L, 1010084621L, 1010084621L, 1010084621L, 1010084621L, 
1010084621L, 1010084621L, 1010084621L, 1010084621L, 1010084621L, 
1010084621L), name = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 3L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L), .Label = c("avic", "bjcf", "bjz"), class = "factor"), 
    date = structure(c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 
    11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 1L, 2L, 3L, 
    4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 
    17L, 18L, 19L, 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 
    12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L), .Label = c("2019-05", 
    "2019-06", "2019-07", "2019-08", "2019-09", "2019-10", "2019-11", 
    "2019-12", "2020-01", "2020-02", "2020-03", "2020-04", "2020-05", 
    "2020-06", "2020-07", "2020-08", "2020-09", "2020-10", "2020-11"
    ), class = "factor"), price = c(11.62, 11.27, 10.25, 9.53, 
    10, 9.12, 8.76, 8.15, 7.92, 9, 8.53, 8.3, 8.45, 8.35, 8.38, 
    8.37, 8.35, 8.29, 8.32, 5.68, 5.68, 5.4, 5.4, 5.4, 5.4, 5.4, 
    5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 5.4, 
    12.82, 13.9, 13.9, 11.81, 11.12, 10.87, 10.33, 9.35, 9.41, 
    9.46, 9.68, 9.2, 9.19, 8.79, 8.79, 8.74, 8.68, 8.92, 8.6)), class = "data.frame", row.names = c(NA, 
-57L))
 

Мне нужно id сгруппировать и name , затем вычислить yearly percentage changes и monthly percentage changes для price столбца. Я использовал следующий код:

 df %>%
  arrange(city, id, date) %>%
  group_by(c(id, name)) %>%
  mutate(monthly_pct_changes = round((price / lag(price) - 1) * 100, 2),
         yearly_pct_changes = round((price / lag(price, 12) - 1) * 100, 2)) 
 

Но это вызывает ошибку:

 error: Problem with `mutate()` input `..1`. x Input `..1` can't be recycled to size 57. ℹ Input `..1` is `c(id, name)`. ℹ Input `..1` must be size 57 or 1, not 114. Run `rlang::last_error()` to see where the error occurred.
 

Как я мог это сделать правильно? Спасибо.

Комментарии:

1. Попробуйте с group_by(id, name) помощью .

2. Спасибо, мне нужно что-то добавить mutate(date = lubridate::ymd(paste0(date, '-01'))) ?

3. Конечно, вы можете, но я не знаю, зачем это нужно или не нужно, поскольку в вашем вопросе ничего не упоминается об изменении столбца даты. @ahbon

Ответ №1:

Модифицированный код, благодаря @ekoam:

 df %>%
  arrange(city, id, date) %>%
  group_by(id, name) %>%
  mutate(monthly_pct_changes = round((price / lag(price) - 1) * 100, 2),
         yearly_pct_changes = round((price / lag(price, 12) - 1) * 100, 2))