查找面板数据自上次更改以来的累积值变化和时间
Find cumulative value change and time since last change in panel data
我有面板数据(下面的小数据示例),并且想要计算变量更改的时间以及自上次更改以来的时间。最终目标是获得两个变量:任意给定年份的累积变化(即当前值与起始值之间的差值),以及自上次变化以来的时间。
# example data
structure(list(rcode = c("DE1", "DE1", "DE1", "DE1", "DE1", "DE1", "DE1", "DE1", "DE1",
"DE1", "DE1", "DE2", "DE2", "DE2", "DE2", "DE2", "DE2", "DE2",
"DE2", "DE2", "DE2", "DE2"),
n_RAI = c(34.47871, 34.91596, 34.91596, 34.88745, 34.79049, 34.79049,
34.79049, 35.48414, 35.98985, 35.98985, 36.98985, 34.47871,
34.91596, 34.91596, 34.88745, 34.79049, 34.79049, 34.79049,
35.48414, 35.98985, 35.98985, 36.98985),
year = c(2000L, 2001L, 2002L, 2003L, 2004L, 2005L, 2006L, 2007L, 2008L,
2009L, 2010L, 2000L, 2001L, 2002L, 2003L, 2004L, 2005L, 2006L,
2007L, 2008L, 2009L, 2010L)),
row.names = 375:396, class = "data.frame")
在这个数据中,r_code
是个人标识符,n_RAI
是我要滞后的变量,year
是时间变量。
使用答案 。
可以很简单地确定小组中每个人何时发生变化。
我苦苦挣扎的地方是想出一个函数,使用 dplyr::group_by
或 tapply
应用于小组中的个人,还可以计算自上次更改以来的时间。本质上,我需要一个函数来识别何时发生变化,开始向上计数,然后在发生另一个变化时重置。这看起来很简单,但我遇到了一些心理障碍,想不出如何将其转化为 R。是否有一个我没有看到的函数或一个简单的基本 R 方法来做到这一点?
例如单个 DE1 的预期输出,使用“change”作为变量名称来标识更改,“t_since”作为自上次更改以来的时间:
change = 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0
t_since = 0, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2
我认为这行得通。这有点令人费解。 t_since
结果与您想要的结果相匹配,change
列与您在问题中显示的内容略有不同,但我认为这可能是您问题中的错字。 (调用你的数据dd
。)
dd = dd %>%
group_by(rcode) %>%
mutate(
change = c(0, abs(diff(n_RAI)) > 1e-8),
grouper = (cumsum(change) - 1) %/% 2
) %>%
group_by(rcode, grouper) %>%
mutate(t_since = pmax(0, 0:(n() - 1))) %>%
ungroup() %>%
select(-grouper)
change = c(0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0)
t_since = c(0, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2)
dd = cbind(dd, goal_change = change, goal_t_since = t_since)
all(dd$goal_change == dd$change)
# [1] FALSE
all(dd$goal_t_since == dd$t_since)
# [1] TRUE
我有面板数据(下面的小数据示例),并且想要计算变量更改的时间以及自上次更改以来的时间。最终目标是获得两个变量:任意给定年份的累积变化(即当前值与起始值之间的差值),以及自上次变化以来的时间。
# example data
structure(list(rcode = c("DE1", "DE1", "DE1", "DE1", "DE1", "DE1", "DE1", "DE1", "DE1",
"DE1", "DE1", "DE2", "DE2", "DE2", "DE2", "DE2", "DE2", "DE2",
"DE2", "DE2", "DE2", "DE2"),
n_RAI = c(34.47871, 34.91596, 34.91596, 34.88745, 34.79049, 34.79049,
34.79049, 35.48414, 35.98985, 35.98985, 36.98985, 34.47871,
34.91596, 34.91596, 34.88745, 34.79049, 34.79049, 34.79049,
35.48414, 35.98985, 35.98985, 36.98985),
year = c(2000L, 2001L, 2002L, 2003L, 2004L, 2005L, 2006L, 2007L, 2008L,
2009L, 2010L, 2000L, 2001L, 2002L, 2003L, 2004L, 2005L, 2006L,
2007L, 2008L, 2009L, 2010L)),
row.names = 375:396, class = "data.frame")
在这个数据中,r_code
是个人标识符,n_RAI
是我要滞后的变量,year
是时间变量。
使用答案
我苦苦挣扎的地方是想出一个函数,使用 dplyr::group_by
或 tapply
应用于小组中的个人,还可以计算自上次更改以来的时间。本质上,我需要一个函数来识别何时发生变化,开始向上计数,然后在发生另一个变化时重置。这看起来很简单,但我遇到了一些心理障碍,想不出如何将其转化为 R。是否有一个我没有看到的函数或一个简单的基本 R 方法来做到这一点?
例如单个 DE1 的预期输出,使用“change”作为变量名称来标识更改,“t_since”作为自上次更改以来的时间:
change = 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0
t_since = 0, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2
我认为这行得通。这有点令人费解。 t_since
结果与您想要的结果相匹配,change
列与您在问题中显示的内容略有不同,但我认为这可能是您问题中的错字。 (调用你的数据dd
。)
dd = dd %>%
group_by(rcode) %>%
mutate(
change = c(0, abs(diff(n_RAI)) > 1e-8),
grouper = (cumsum(change) - 1) %/% 2
) %>%
group_by(rcode, grouper) %>%
mutate(t_since = pmax(0, 0:(n() - 1))) %>%
ungroup() %>%
select(-grouper)
change = c(0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0)
t_since = c(0, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2)
dd = cbind(dd, goal_change = change, goal_t_since = t_since)
all(dd$goal_change == dd$change)
# [1] FALSE
all(dd$goal_t_since == dd$t_since)
# [1] TRUE