【问题标题】:Moving average and moving slope in RR中的移动平均线和移动斜率
【发布时间】:2018-02-03 17:23:48
【问题描述】:

我希望分别计算“oldvar”的 7 天 moving average 和 7 天 moving slope

对于我没有在原始帖子中添加以下详细信息,我深表歉意。这些是对每个 id 的重复观察,可以从每个 id 至少 3 个观察到每个 id 100 个观察。不同 ID 的开始日期可能不同,而且为了使事情变得复杂,日期间隔不相等,因此某些 ID 缺少天数。

这是数据结构。请注意,“平均值”是我尝试创建的变量,作为每个 ID 的 7 天移动平均值:

id  day outcome average
1   1   15  100 NA    
2   1   16  110 NA    
3   1   17  190 NA    
4   1   18  130 NA    
5   1   19  140 NA    
6   1   20  150 NA    
7   1   21  160 140    
8   1   22  100 140    
9   1   23  180 150    
10  1   24  120 140    
12  2   16  90  NA    
13  2   17  110 NA    
14  2   18  120 NA    
12  2   20  130 NA    
15  3   16  110 NA    
16  3   18  200 NA    
17  3   19  180 NA    
18  3   21  170 NA    
19  3   22  180 168    
20  3   24  210 188    
21  3   25  160 180    
22  3   27  200 184    

另外,希望得到有关如何计算 moving 7-day slope 的建议。

感谢您,再次为第一次不清楚的地方再次道歉。

【问题讨论】:

  • 请提供数据集

标签: r moving-average


【解决方案1】:

真正的挑战是在完成缺失的行后创建data.frame。一种解决方案是使用zoo 库。 rollapply 函数将提供一种为初始行分配 NA 值的方法。

按原样使用来自 OP 的数据,解决方案可能是:

library(zoo)
library(dplyr)

# Data from OP
df <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                  2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), 
     day = c(15L,16L, 17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L, 16L, 17L, 18L, 20L, 
                16L, 18L, 19L, 21L, 22L, 24L, 25L, 27L), 
     outcome = c(100L, 110L,190L, 130L, 140L, 150L, 160L, 100L, 180L, 120L, 90L, 110L, 120L, 
                      130L, 110L, 200L, 180L, 170L, 180L, 210L, 160L, 200L)), 
      .Names = c("id", "day", "outcome"), row.names = c(NA, -22L), class = "data.frame")

# Make a list without missing day for each id
df_complete <- merge(
  expand.grid(id=unique(df$id), day=min(df$day):max(df$day)),
              df, all=TRUE)

# Valid range of day for each ID group
df_id_wise_range <- df %>% group_by(id) %>% 
  summarise(min_day = min(day), max_day = max(day)) %>% as.data.frame()

# id min_day max_day
# 1  1      15      24
# 2  2      16      20
# 3  3      16      27

# Join original df and df_complete and then use df_id_wise_range to 
# filter it for valid range of day for each group
df_final <- df_complete %>%
          left_join(df, by=c("id","day")) %>%
          select(-outcome.y) %>%
          inner_join(df_id_wise_range, by="id") %>%
          filter(day >= min_day & day <= max_day) %>%
          mutate(outcome = outcome.x) %>%
          select( id, day, outcome) %>%
          as.data.frame()

# Now apply mean to get average
df_average <- df_final %>% group_by(id) %>%
  mutate(average= rollapply(outcome, 7, mean, na.rm = TRUE, by = 1, 
          fill = NA, align = "right", partial = 7)) %>% as.data.frame()

df_average
# The result
#   id day outcome average
#1   1  15     100      NA
#2   1  16     110      NA
#3   1  17     190      NA
#4   1  18     130      NA
#5   1  19     140      NA
#6   1  20     150      NA
#7   1  21     160   140.0
#8   1  22     100   140.0
#9   1  23     180   150.0
#10  1  24     120   140.0
#11  2  16      90      NA
#12  2  17     110      NA
#13  2  18     120      NA
#.... 
#....
#19  3  19     180      NA
#20  3  20      NA      NA
#21  3  21     170      NA
#22  3  22     180   168.0
#23  3  23      NA   182.5
#24  3  24     210   188.0
#25  3  25     160   180.0
#26  3  26      NA   180.0
#27  3  27     200   184.0

计算moving slope的步骤是: 首先创建一个函数来返回斜率 使用函数作为rollapplyr的一部分

#Function to calculate slope
slop_e <- function(z) coef(lm(b ~ a, as.data.frame(z)))[[2]]
#Apply function
z2$slope <- rollapplyr(zoo(z2), 7, slop_e , by.column = FALSE, fill = NA, align = "right")

z2
    a  b mean_a slope
1   1 21 NA    NA
2   2 22 NA    NA
3   3 23 NA    NA
4   4 24 NA    NA
5   5 25 NA    NA
6   6 26 NA    NA
7   7 27  4     1
8   8 28  5     1
9   9 29  6     1
10 10 30  7     1
11 11 31  8     1
12 12 32  9     1
13 13 33 10     1
14 14 34 11     1
15 15 35 12     1
16 16 36 13     1
17 17 37 14     1
18 18 38 15     1
19 19 39 16     1
20 20 40 17     1

【讨论】:

  • 非常感谢 MKR。非常感激。我已经编辑并澄清了我的问题。很抱歉我第一次不清楚。
  • @syork 我已修改我的答案以使用您提供的数据。该解决方案将处理average 值。您必须使用df_final 来计算slope,如我在示例中所示。如果您遇到任何问题,请告诉我。这个问题很好回答。
  • 非常感谢 MKR。我正在尝试,但无法安装 dplyr。我正在研究这个只有 R 版本 3.3.0 的烦人的避风港,我无法更新它。 dplyr 似乎是在 R v3.4.1 下开发的。我尝试了 r-oldrel 版本,但没有任何乐趣。关于如何解决这个问题的任何想法?我只能使用 Windows 二进制文件导入包。抱歉,这超出了最初的问题,但我将感谢您的帮助。谢谢!
  • 谢谢你,MKR。我正在努力解决避风港问题。与此同时,我在笔记本电脑上尝试了您的解决方案。在计算 df_average 的步骤之前它工作正常。我收到错误消息:“错误:不兼容的类型,需要一个数字向量”。我错过了什么明显的东西吗?谢谢。
  • 工作愉快!绝对天才!在我更新 R 后,我在之前评论中提到的错误消失了。Massive 谢谢!
猜你喜欢
  • 2017-09-01
  • 2017-04-24
  • 2018-10-21
  • 2022-01-26
  • 2013-12-22
  • 1970-01-01
  • 2016-05-16
  • 2021-07-10
  • 2020-02-04
相关资源
最近更新 更多