dplyr 滞后与列值中的 n
Posted
技术标签:
【中文标题】dplyr 滞后与列值中的 n【英文标题】:dplyr lag with n from column values 【发布时间】:2018-08-28 08:08:40 【问题描述】:是否可以在 dplyr::lag 函数中使用列值作为 n?
可重现的例子:
DF <- data.frame(
V = runif(1000, min=-100, max=100),
nlag = as.integer(runif(1000, min=1, max=10))
) %>%
mutate(Vlag = lag(V, n = nlag))
我得到这个错误:
错误:评估错误:
n
必须是非负整数标量,而不是长度为 1000 的整数。
还有其他选择吗?
更新:
我们如何在小组内解决相同的问题?
可重现的例子:
DF <- data.frame(
V = runif(1000, min=-100, max=100),
nlag = as.integer(runif(1000, min=1, max=10)),
type = sample(1:4, replace=TRUE)
) %>%
group_by(type) %>%
mutate(Vlag = lag(V, n = nlag))
【问题讨论】:
【参考方案1】:?lag
的文档说
n 长度为 1 的正整数,给出领先或落后的位置数
所以不可能给出任何大于 length = 1
的数字。
但是,我们可以通过用相应的nlag
值减去当前行索引来生成索引以获取V
值,然后我们使用该索引来获取滞后的V
值。
df$lag_value <- sapply(seq_along(df$nlag), function(x)
indx = x - df$nlag[x]
if(indx > 0)
df$V[indx]
else
NA
)
df
# V nlag lag_value
#1 51.30453 6 NA
#2 -66.33709 4 NA
#3 95.45096 9 NA
#4 44.54434 3 51.30453
#5 62.00180 3 -66.33709
#6 -18.43012 4 -66.33709
更新
如果我们想按组执行此操作,我们可以按type
列拆分它们并应用相同的操作。
df$lag_value <- unlist(lapply(split(df, df$type), function(x)
sapply(seq_along(x$nlag), function(y)
indx = y - x$nlag[y]
if(indx > 0)
x$V[indx]
else
NA
)))
数据
df <- head(DF)
【讨论】:
【参考方案2】:nlag
的长度必须为 1,试试这样:
DF <- data.frame(
V = runif(1000, min=-100, max=100),
nlag = as.integer(runif(1000, min=1, max=10))
) %>% mutate(Vlag = V[if_else((row_number() - nlag) < 1, as.integer(NA), row_number() - nlag)])
V nlag Vlag
1 -6.72598341 4 NA
2 -84.67472238 2 NA
3 -4.98048104 7 NA
4 2.64957272 4 NA
5 82.16284532 4 -6.72598341
6 28.93483448 9 NA
7 88.16730371 3 2.64957272
8 42.31721302 7 -6.72598341
9 -38.12659876 1 42.31721302
10 74.62628153 3 88.16730371
...
【讨论】:
【参考方案3】:另一个选项是使用purrr
-package。 map2_dbl
将两个长度相同的向量(或列表)作为输入,并同时迭代它们。然后返回一个double
。在map
调用中,V 的lag
使用指定的`nlag 计算,然后仅返回当前行。
library(dplyr)
library(purrr)
DF %>%
mutate(Vlag = map2_dbl(nlag, row_number(), ~ lag(V, n = .x)[.y]))
# A tibble: 20 x 3
# V nlag Vlag
# <dbl> <int> <dbl>
# 1 83.0 9 NA
# 2 87.4 2 NA
# 3 -42.8 9 NA
# 4 66.1 9 NA
# 5 28.3 1 66.1
# 6 3.82 5 83.0
# 7 47.3 4 -42.8
# 8 -73.1 9 NA
# 9 31.4 5 66.1
# 10 41.0 8 87.4
# ...
数据 当使用随机数作为示例时,您应该指定一个种子。同样在这种情况下,较少的行数就足以显示问题。
set.seed(42)
DF <- tibble(V = runif(20, min=-100, max=100),
nlag = as.integer(runif(20, min=1, max=10)))
【讨论】:
【参考方案4】:我认为这比当前的答案要干净一些:
DF %>%
group_by(ID, nlag) %>%
mutate(Vlag = dplyr::lag(V, n = nlag[1])) %>%
ungroup()
由于它是分组nlag
,所有索引都是相同的,所以取第一个就可以了。
【讨论】:
以上是关于dplyr 滞后与列值中的 n的主要内容,如果未能解决你的问题,请参考以下文章