如何获得频率滞后周期的平均值作为r中的新变量
How to get average of lag period in a frequency as a new variable in r
我正在尝试安排我的面板数据集以使用定期出现的滞后期的平均值来创建新变量。我的示例数据集如下所示,可以使用以下代码访问
Time ID Value1 Value2
1 Jan-14 A 12 NA
2 Feb-14 A 14 NA
3 Mar-14 A 15 NA
4 Apr-14 A 18 NA
5 May-14 A 10 NA
6 Jun-14 A 12 13.67
7 Jul-14 A 13 15.67
8 Aug-14 A 14 14.33
9 Jan-14 B 32 NA
10 Feb-14 B 14 NA
11 Mar-14 B 15 NA
12 Apr-14 B 18 NA
13 May-14 B 20 NA
14 Jun-14 B 12 20.33
15 Jul-14 B 13 15.67
16 Aug-14 B 14 17.78
df<-structure(list(Time = structure(c(4L, 3L, 7L, 1L, 8L, 6L, 5L,
2L, 4L, 3L, 7L, 1L, 8L, 6L, 5L, 2L), .Label = c("Apr-14", "Aug-14",
"Feb-14", "Jan-14", "Jul-14", "Jun-14", "Mar-14", "May-14"), class = "factor"),
ID = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L), .Label = c("A", "B"), class = "factor"),
Value1 = c(12L, 14L, 15L, 18L, 10L, 12L, 13L, 14L, 32L, 14L,
15L, 18L, 20L, 12L, 13L, 14L)), .Names = c("Time", "ID",
"Value1"), class = "data.frame", row.names = c(NA, -16L))
我想创建一个名为 Value2 的新变量,考虑到每次观察对应于前 4-6 个月的 3 个月的平均值(这只是为了举例,我的月度数据集在 40 个人中持续 12 年,而且我将不得不考虑比 3 个月更高的延迟,也许 14 个月)。在这里我还需要考虑 ID,因为需要保留面板结构。 3 个月前未完成的所有观测值,应表示为NA
。例如 Jun_14_A
应该得到从 Mar_14_A
到 Jan_14_A
的平均值。 (12+14+15)/3 =13.67
我提到了一些例子 here 但这些例子并没有提供我正在寻找的特别滞后平均值,并且在没有前 3 个完整月份时表示为 NA 。
提前感谢您的帮助
一种方法,它没有改进,所以也许有人(如果我有时间的话)稍后会提出一个更优雅的解决方案:
首先是将您的 df$time
转换为实际日期。
library(zoo)
df$Time=as.yearmon(as.character(df$Time),"%b-%y")
library(dplyr)
df%>%
group_by(ID)%>%
mutate(Value2 = ( lag(Value1, 3) + lag(Value1, 4) + lag(Value1, 5) ) / 3)
Time ID Value1 Value2
<fctr> <fctr> <int> <dbl>
1 Jan-14 A 12 NA
2 Feb-14 A 14 NA
3 Mar-14 A 15 NA
4 Apr-14 A 18 NA
5 May-14 A 10 NA
6 Jun-14 A 12 13.66667
7 Jul-14 A 13 15.66667
8 Aug-14 A 14 14.33333
9 Jan-14 B 32 NA
10 Feb-14 B 14 NA
11 Mar-14 B 15 NA
12 Apr-14 B 18 NA
13 May-14 B 20 NA
14 Jun-14 B 12 20.33333
15 Jul-14 B 13 15.66667
16 Aug-14 B 14 17.66667
我创建了滞后 3、4 和 5 的 3 个变量,并简单地计算平均值,任何 NA(不是 3 个完整月)都将 return NA。
我们可以试试:
library(data.table)
setDT(df)
f <- function(x) if(anyNA(x[1:6])) NA else mean(x[1:3])
df[, Value2 := zoo::rollapply(Value1, 6, f, align = "right", partial = TRUE), by = ID]
> df
Time ID Value1 Value2
1: Jan-14 A 12 NA
2: Feb-14 A 14 NA
3: Mar-14 A 15 NA
4: Apr-14 A 18 NA
5: May-14 A 10 NA
6: Jun-14 A 12 13.66667
7: Jul-14 A 13 15.66667
8: Aug-14 A 14 14.33333
9: Jan-14 B 32 NA
10: Feb-14 B 14 NA
11: Mar-14 B 15 NA
12: Apr-14 B 18 NA
13: May-14 B 20 NA
14: Jun-14 B 12 20.33333
15: Jul-14 B 13 15.66667
16: Aug-14 B 14 17.66667
这是另一种使用 data.table
的方法,它是 shift
函数结合 Reduce
(这几乎是对 的欺骗)
library(data.table)
setDT(df)[, Value2 := Reduce(`+`, shift(Value1, 3:5))/3, by = ID]
df
# Time ID Value1 Value2
# 1: Jan-14 A 12 NA
# 2: Feb-14 A 14 NA
# 3: Mar-14 A 15 NA
# 4: Apr-14 A 18 NA
# 5: May-14 A 10 NA
# 6: Jun-14 A 12 13.66667
# 7: Jul-14 A 13 15.66667
# 8: Aug-14 A 14 14.33333
# 9: Jan-14 B 32 NA
# 10: Feb-14 B 14 NA
# 11: Mar-14 B 15 NA
# 12: Apr-14 B 18 NA
# 13: May-14 B 20 NA
# 14: Jun-14 B 12 20.33333
# 15: Jul-14 B 13 15.66667
# 16: Aug-14 B 14 17.66667
尝试 rollapplyr
来自动物园。 list(-3:-5)
的宽度意味着它将在每次迭代中使用从当前点偏移 -3、-4 和 -5 的组件:
library(zoo)
roll <- function(x) rollapplyr(x, list(-3:-5), mean, fill = NA)
transform(df, Value2 = ave(Value1, ID, FUN = roll))
给出以下数据框:
Time ID Value1 Value2
1 Jan-14 A 12 NA
2 Feb-14 A 14 NA
3 Mar-14 A 15 NA
4 Apr-14 A 18 NA
5 May-14 A 10 NA
6 Jun-14 A 12 13.66667
7 Jul-14 A 13 15.66667
8 Aug-14 A 14 14.33333
9 Jan-14 B 32 NA
10 Feb-14 B 14 NA
11 Mar-14 B 15 NA
12 Apr-14 B 18 NA
13 May-14 B 20 NA
14 Jun-14 B 12 20.33333
15 Jul-14 B 13 15.66667
16 Aug-14 B 14 17.66667
注意:虽然我们没有做出更改,因为不需要回答问题,但请注意,您可能希望使用 zoo 的 "yearmon"
class 第一列。使用 class year/month 值可以正确排序但显示效果很好。即,
transform(df, Time = as.yearmon(Time, "%b-%y"), Value2 = ...as above...)
我正在尝试安排我的面板数据集以使用定期出现的滞后期的平均值来创建新变量。我的示例数据集如下所示,可以使用以下代码访问
Time ID Value1 Value2
1 Jan-14 A 12 NA
2 Feb-14 A 14 NA
3 Mar-14 A 15 NA
4 Apr-14 A 18 NA
5 May-14 A 10 NA
6 Jun-14 A 12 13.67
7 Jul-14 A 13 15.67
8 Aug-14 A 14 14.33
9 Jan-14 B 32 NA
10 Feb-14 B 14 NA
11 Mar-14 B 15 NA
12 Apr-14 B 18 NA
13 May-14 B 20 NA
14 Jun-14 B 12 20.33
15 Jul-14 B 13 15.67
16 Aug-14 B 14 17.78
df<-structure(list(Time = structure(c(4L, 3L, 7L, 1L, 8L, 6L, 5L,
2L, 4L, 3L, 7L, 1L, 8L, 6L, 5L, 2L), .Label = c("Apr-14", "Aug-14",
"Feb-14", "Jan-14", "Jul-14", "Jun-14", "Mar-14", "May-14"), class = "factor"),
ID = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L), .Label = c("A", "B"), class = "factor"),
Value1 = c(12L, 14L, 15L, 18L, 10L, 12L, 13L, 14L, 32L, 14L,
15L, 18L, 20L, 12L, 13L, 14L)), .Names = c("Time", "ID",
"Value1"), class = "data.frame", row.names = c(NA, -16L))
我想创建一个名为 Value2 的新变量,考虑到每次观察对应于前 4-6 个月的 3 个月的平均值(这只是为了举例,我的月度数据集在 40 个人中持续 12 年,而且我将不得不考虑比 3 个月更高的延迟,也许 14 个月)。在这里我还需要考虑 ID,因为需要保留面板结构。 3 个月前未完成的所有观测值,应表示为NA
。例如 Jun_14_A
应该得到从 Mar_14_A
到 Jan_14_A
的平均值。 (12+14+15)/3 =13.67
我提到了一些例子 here 但这些例子并没有提供我正在寻找的特别滞后平均值,并且在没有前 3 个完整月份时表示为 NA 。
提前感谢您的帮助
一种方法,它没有改进,所以也许有人(如果我有时间的话)稍后会提出一个更优雅的解决方案:
首先是将您的 df$time
转换为实际日期。
library(zoo)
df$Time=as.yearmon(as.character(df$Time),"%b-%y")
library(dplyr)
df%>%
group_by(ID)%>%
mutate(Value2 = ( lag(Value1, 3) + lag(Value1, 4) + lag(Value1, 5) ) / 3)
Time ID Value1 Value2
<fctr> <fctr> <int> <dbl>
1 Jan-14 A 12 NA
2 Feb-14 A 14 NA
3 Mar-14 A 15 NA
4 Apr-14 A 18 NA
5 May-14 A 10 NA
6 Jun-14 A 12 13.66667
7 Jul-14 A 13 15.66667
8 Aug-14 A 14 14.33333
9 Jan-14 B 32 NA
10 Feb-14 B 14 NA
11 Mar-14 B 15 NA
12 Apr-14 B 18 NA
13 May-14 B 20 NA
14 Jun-14 B 12 20.33333
15 Jul-14 B 13 15.66667
16 Aug-14 B 14 17.66667
我创建了滞后 3、4 和 5 的 3 个变量,并简单地计算平均值,任何 NA(不是 3 个完整月)都将 return NA。
我们可以试试:
library(data.table)
setDT(df)
f <- function(x) if(anyNA(x[1:6])) NA else mean(x[1:3])
df[, Value2 := zoo::rollapply(Value1, 6, f, align = "right", partial = TRUE), by = ID]
> df
Time ID Value1 Value2
1: Jan-14 A 12 NA
2: Feb-14 A 14 NA
3: Mar-14 A 15 NA
4: Apr-14 A 18 NA
5: May-14 A 10 NA
6: Jun-14 A 12 13.66667
7: Jul-14 A 13 15.66667
8: Aug-14 A 14 14.33333
9: Jan-14 B 32 NA
10: Feb-14 B 14 NA
11: Mar-14 B 15 NA
12: Apr-14 B 18 NA
13: May-14 B 20 NA
14: Jun-14 B 12 20.33333
15: Jul-14 B 13 15.66667
16: Aug-14 B 14 17.66667
这是另一种使用 data.table
的方法,它是 shift
函数结合 Reduce
(这几乎是对
library(data.table)
setDT(df)[, Value2 := Reduce(`+`, shift(Value1, 3:5))/3, by = ID]
df
# Time ID Value1 Value2
# 1: Jan-14 A 12 NA
# 2: Feb-14 A 14 NA
# 3: Mar-14 A 15 NA
# 4: Apr-14 A 18 NA
# 5: May-14 A 10 NA
# 6: Jun-14 A 12 13.66667
# 7: Jul-14 A 13 15.66667
# 8: Aug-14 A 14 14.33333
# 9: Jan-14 B 32 NA
# 10: Feb-14 B 14 NA
# 11: Mar-14 B 15 NA
# 12: Apr-14 B 18 NA
# 13: May-14 B 20 NA
# 14: Jun-14 B 12 20.33333
# 15: Jul-14 B 13 15.66667
# 16: Aug-14 B 14 17.66667
尝试 rollapplyr
来自动物园。 list(-3:-5)
的宽度意味着它将在每次迭代中使用从当前点偏移 -3、-4 和 -5 的组件:
library(zoo)
roll <- function(x) rollapplyr(x, list(-3:-5), mean, fill = NA)
transform(df, Value2 = ave(Value1, ID, FUN = roll))
给出以下数据框:
Time ID Value1 Value2
1 Jan-14 A 12 NA
2 Feb-14 A 14 NA
3 Mar-14 A 15 NA
4 Apr-14 A 18 NA
5 May-14 A 10 NA
6 Jun-14 A 12 13.66667
7 Jul-14 A 13 15.66667
8 Aug-14 A 14 14.33333
9 Jan-14 B 32 NA
10 Feb-14 B 14 NA
11 Mar-14 B 15 NA
12 Apr-14 B 18 NA
13 May-14 B 20 NA
14 Jun-14 B 12 20.33333
15 Jul-14 B 13 15.66667
16 Aug-14 B 14 17.66667
注意:虽然我们没有做出更改,因为不需要回答问题,但请注意,您可能希望使用 zoo 的 "yearmon"
class 第一列。使用 class year/month 值可以正确排序但显示效果很好。即,
transform(df, Time = as.yearmon(Time, "%b-%y"), Value2 = ...as above...)