我想在一个组中创建一个包含上一年变量值的变量。
id date value
1 1 1992 4.1
2 1 NA 4.5
3 1 1991 3.3
4 1 1990 5.3
5 1 1994 3.0
6 2 1992 3.2
7 2 1991 5.2
当组中缺少前一年时, value_lagged
应该丢失 - 或者因为它是组内的第一个日期(如第4,7行),或者因为数据中存在年份缺口(如第5行)。此外,当缺少当前时间时,value_lagged
应该丢失(如第2行)。
这给出了:
id date value value_lagged
1 1 1992 4.1 3.3
2 1 NA 4.5 NA
3 1 1991 3.3 5.3
4 1 1990 5.3 NA
5 1 1994 3.0 NA
6 2 1992 3.2 5.2
7 2 1991 5.2 NA
目前,在R中,我使用data.table
包
DT = data.table(id = c(1,1,1,1,1,2,2),
date = c(1992,NA,1991,1990,1994,1992,1991),
value = c(4.1,4.5,3.3,5.3,3.0,3.2,5.2)
)
setkey(DT, id, date)
DT[, value_lagged := DT[J(id, date-1), value], ]
DT[is.na(date), value_lagged := NA, ]
它很快但似乎有点容易出错。我想知道使用data.table
,dplyr
或任何其他软件包是否有更好的替代方案。非常感谢!
在Stata
中,人们可以这样做:
tsset id date
gen value_lagged=L.value
答案 0 :(得分:9)
我可能会使用连接解决这个问题:
library(dplyr)
df <- data.frame(
id = c(1, 1, 1, 1, 1, 2, 2),
date = c(1992, NA, 1991, 1990, 1994, 1992, 1991),
value = c(4.1, 4.5, 3.3, 5.3, 3.0, 3.2, 5.2)
)
last_year <- df %>%
filter(!is.na(date)) %>%
mutate(date = date + 1, lagged_value = value, value = NULL)
df %>%
left_join(last_year)
#> Joining by: c("id", "date")
#> id date value lagged_value
#> 1 1 1992 4.1 3.3
#> 2 1 NA 4.5 NA
#> 3 1 1991 3.3 5.3
#> 4 1 1990 5.3 NA
#> 5 1 1994 3.0 NA
#> 6 2 1992 3.2 5.2
#> 7 2 1991 5.2 NA
答案 1 :(得分:7)
在tlag
id
library(dplyr)
tlag <- function(x, n = 1L, time) {
index <- match(time - n, time, incomparables = NA)
x[index]
}
df %>% group_by(id) %>% mutate(value_lagged = tlag(value, 1, time = date))
答案 2 :(得分:3)
使用1.9.5
,其中连接不需要设置键,可以按如下方式完成:
require(data.table) # v1.9.5+
DT[!is.na(date), value_lagged :=
.SD[.(id = id, date = date - 1), value, on = c("id", "date")]]
# id date value value_lagged
# 1: 1 1992 4.1 3.3
# 2: 1 NA 4.5 NA
# 3: 1 1991 3.3 5.3
# 4: 1 1990 5.3 NA
# 5: 1 1994 3.0 NA
# 6: 2 1992 3.2 5.2
# 7: 2 1991 5.2 NA
这是你想法的变体。诀窍是直接在is.na()
中使用i
并在.SD
中使用j
而不是DT
。我使用了on=
语法,但同样的想法当然可以通过设置键来完成。
答案 3 :(得分:0)
collapse
包现在提供了一种优雅而快速的通用解决方案,用于计算不规则时间序列和不平衡面板,其中包含函数 flag
、fdiff
和 fgrowth
。查看滞后不平衡面板 here 的一般答案。
现在在您的特定应用程序中,还有一个罕见的事实,即面板不仅不平衡,而且您的时间变量中还有一个缺失值,这意味着您不知道观察记录的时间段。在这种情况下,仅应用 collapse::flag
是行不通的,但您可以生成一个新的 id 变量,将缺失值与 collapse::seqid
放在一个单独的组中。所以我的解决方案是:
library(collapse)
DF = data.frame(id = c(1,1,1,1,1,2,2),
date = c(1992,NA,1991,1990,1994,1992,1991),
value = c(4.1,4.5,3.3,5.3,3.0,3.2,5.2))
settransform(DF, l_value = flag(value, 1, g = seqid(date, order(id, date)), t = date))
DF
#> id date value l_value
#> 1 1 1992 4.1 3.3
#> 2 1 NA 4.5 NA
#> 3 1 1991 3.3 5.3
#> 4 1 1990 5.3 NA
#> 5 1 1994 3.0 NA
#> 6 2 1992 3.2 5.2
#> 7 2 1991 5.2 NA
由 reprex package (v0.3.0) 于 2021 年 7 月 10 日创建
我非常有信心这仍然比 data.table
快,但我还没有测试过。同样,这个数据相当奇怪,对于大多数面板不平衡但记录都由 id 和时间标识的情况,简单的 flag(value, 1, id, as.integer(date))
会很好并且很快。请注意,您可以通过确保时间变量为整数来提高效率,因为 flag
将强制非整数时间变量进行因子分解,这也可以消除不规则性。