Как создать новый столбец с скользящими средними на основе переменного числа строк? - PullRequest
1 голос
/ 05 ноября 2019

Я пытаюсь написать код, который создает новый столбец со скользящими средними на основе 'year', где количество строк для каждого года является переменной, где каждый год имеет только одно уникальное значение, повторяющееся для каждой строки этого года. Я хочу рассчитать скользящие средние на основе этих уникальных значений независимо от количества строк в году.

Просто к вашему сведению;Я очень плохо знаком с R и программированием, поэтому, если я что-то упустил, чтобы вы поняли мою проблему, пожалуйста, дайте мне знать.

Например, тип данных, с которыми я работаю, выглядит следующим образом:

df <- data.frame(year = c(1702, 1702, 1702, 1702,   1702,   1703,   1703,   1703,   1704,   1704,   1705,   1705,   1705,   1705,   1706,   1706,   1707,   1707,   1707, 1708, 1708,   1708,   1708,   1708,   1709,   1709,   1709,   1709,   1709), avgtemp = c(5.3, 5.3,    5.3,    5.3,    5.3,    3.9,    3.9,    3.9,    6.12,   6.12,   4.16,   4.16,   4.16,   4.16,   5.65,   5.65,   3.11,   3.11,   3.11, 5.17, 5.17,   5.17,   5.17,   5.17,   4.75,   4.75,   4.75,   4.75,   4.75))

Я нашел этот пост, Скользящее среднее по уникальной дате с несколькими наблюдениями за датой , и попробовал решение, предложенное там Марком Петерсоном, но оно не работает для меня.

Я пробовал следующий код.

rolledavg <-
  df %>%
  group_by(year) %>%
  summarise(rollavg = mean(avgtemp)) %>%
  ungroup() %>%
  arrange(year) %>%
  mutate( ma3temp = rollapply(rollavg
                              , 3
                              , mean
                              , align= "right"
                              , partial=T
                              , fill = NA))

Я получаю следующую ошибку: «Ошибка в порядке (год): аргумент 1 не является вектором».

Ожидаемый результат должен быть примерно таким:

ожидаемый результат df

Буду признателен за любую помощь, которую смогу получить. Не против работать с другими пакетами / решениями, отличными от предложенных выше.

1 Ответ

1 голос
/ 05 ноября 2019

Как-то так с sapply()?

dat$ra <- sapply(1:nrow(dat), function(n) mean(dat$avgtemp[1:n]))
#    year avgtemp       ra
# 1  1702    5.30 5.300000
# 2  1702    5.30 5.300000
# 3  1702    5.30 5.300000
# 4  1702    5.30 5.300000
# 5  1702    5.30 5.300000
# 6  1703    3.90 5.066667
# 7  1703    3.90 4.900000
# 8  1703    3.90 4.775000
# 9  1704    6.12 4.924444
# 10 1704    6.12 5.044000
# 11 1705    4.16 4.963636
# 12 1705    4.16 4.896667
# 13 1705    4.16 4.840000
# 14 1705    4.16 4.791429
# 15 1706    5.65 4.848667
# 16 1706    5.65 4.898750
# 17 1707    3.11 4.793529
# 18 1707    3.11 4.700000
# 19 1707    3.11 4.616316

Примечание: Если вы хотите использовать только две цифры, используйте round(mean(.), 2).

Обновление

После обновления вашего вопроса выможет вычислить скользящее среднее с filter() 1 из уникальной версии вашего фрейма данных и merge результата с исходным фреймом данных.

dat <- merge(dat, transform(unique(dat), ra=filter(avgtemp, rep(1/3, 3), sides=1)))
#    year avgtemp       ra
# 1  1702    5.30       NA
# 2  1702    5.30       NA
# 3  1702    5.30       NA
# 4  1702    5.30       NA
# 5  1702    5.30       NA
# 6  1703    3.90       NA
# 7  1703    3.90       NA
# 8  1703    3.90       NA
# 9  1704    6.12 5.106667
# 10 1704    6.12 5.106667
# 11 1705    4.16 4.726667
# 12 1705    4.16 4.726667
# 13 1705    4.16 4.726667
# 14 1705    4.16 4.726667
# 15 1706    5.65 5.310000
# 16 1706    5.65 5.310000
# 17 1707    3.11 4.306667
# 18 1707    3.11 4.306667
# 19 1707    3.11 4.306667

Это также возможно с функцией zoo::rollmean().

dat <- merge(dat, transform(unique(dat), ra=c(rep(NA, 3 - 1), zoo::rollmean(avgtemp, 3))))

Данные

dat <- structure(list(year = c(1702, 1702, 1702, 1702, 1702, 1703, 1703, 
1703, 1704, 1704, 1705, 1705, 1705, 1705, 1706, 1706, 1707, 1707, 
1707), avgtemp = c(5.3, 5.3, 5.3, 5.3, 5.3, 3.9, 3.9, 3.9, 6.12, 
6.12, 4.16, 4.16, 4.16, 4.16, 5.65, 5.65, 3.11, 3.11, 3.11)), row.names = c(NA, 
-19L), class = "data.frame")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...