R скользящее среднее между переменными фрейма данных - PullRequest
1 голос
/ 29 января 2020

Я пытаюсь найти решение, но пока не нашел. У меня есть структура данных, структурированная следующим образом:

country City 2014 2015 2016 2017 2018 2019
France  Paris 23   34   54   12   23   21
US       NYC   1    2    2    12   95  54 

Я хочу найти скользящее среднее значение для каждых 3 лет (т. Е. 2014-16, 2015-17 и т. Д. c) для размещения в ad-ho. c столбцы.

country City 2014 2015 2016 2017 2018 2019 2014-2016  2015-2017  2016-2018  2017-2019
France  Paris 23   34   54   12   23   21    37          33.3      29.7        18.7  
US       NYC   1    2    2    12   95  54    etc           etc     etc          etc

Есть подсказка?

1 Ответ

3 голосов
/ 29 января 2020

1) Используя воспроизводимые в примечании данные в конце, мы применяем rollmean к каждому столбцу в транспонировании данных и затем транспонируем обратно. Мы rollapply подходящую команду вставки для создания имен.

library(zoo)

DF2 <- DF[-(1:2)]
cbind(DF, setNames(as.data.frame(t(rollmean(t(DF2), 3))), 
  rollapply(names(DF2), 3, function(x) paste(range(x), collapse = "-"))))

давая:

  country  City 2014 2015 2016 2017 2018 2019 2014-2016 2015-2017 2016-2018 2017-2019
1  France Paris   23   34   54   12   23   21 37.000000 33.333333  29.66667  18.66667
2      US   NYC    1    2    2   12   95   54  1.666667  5.333333  36.33333  53.66667

2) Это также может быть выражено с помощью dplyr / tidyr / зоопарк, как это:

library(dplyr)
library(tidyr)
library(zoo)

DF %>%
  pivot_longer(-c(country, City)) %>%
  group_by(country, City) %>%
  mutate(value = rollmean(value, 3, fill = NA),
    name = rollapply(name, 3, function(x) paste(range(x), collapse="-"), fill=NA)) %>%
  ungroup %>%
  drop_na %>%
  pivot_wider %>%
  left_join(DF, ., by = c("country", "City"))

Примечание

Lines <- "country City 2014 2015 2016 2017 2018 2019
France  Paris 23   34   54   12   23   21
US       NYC   1    2    2    12   95  54 "
DF <- read.table(text = Lines, header = TRUE, as.is = TRUE, check.names = FALSE)
...