gpt4 book ai didi

r - 在单个 R data.table 中按组有效地锁定

转载 作者:行者123 更新时间:2023-12-03 02:34:59 25 4
gpt4 key购买 nike

我有一个又大又宽的data.table(20m 行),以人员 ID 为键,但有很多列(~150),其中有很多空值。每一列都是我希望为每个人继承的记录状态/属性。每个人可能有 10 到 10,000 个观察结果,该集合中约有 500,000 人。一个人的值不能“渗透”到下一个人中,因此我的解决方案必须适本地尊重人员 ID 列和组。

出于演示目的 - 这是一个非常小的示例输入:

DT = data.table(
id=c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3),
aa=c("A", NA, "B", "C", NA, NA, "D", "E", "F", NA, NA, NA),
bb=c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
cc=c(1, NA, NA, NA, NA, 4, NA, 5, 6, NA, 7, NA)
)

看起来像这样:

    id aa bb cc
1: 1 A NA 1
2: 1 NA NA NA
3: 1 B NA NA
4: 1 C NA NA
5: 2 NA NA NA
6: 2 NA NA 4
7: 2 D NA NA
8: 2 E NA 5
9: 3 F NA 6
10: 3 NA NA NA
11: 3 NA NA 7
12: 3 NA NA NA

我的预期输出如下所示:

    id aa bb cc
1: 1 A NA 1
2: 1 A NA 1
3: 1 B NA 1
4: 1 C NA 1
5: 2 NA NA NA
6: 2 NA NA 4
7: 2 D NA 4
8: 2 E NA 5
9: 3 F NA 6
10: 3 F NA 6
11: 3 F NA 7
12: 3 F NA 7

我找到了一个可行的 data.table 解决方案,但它在我的大型数据集上速度非常慢:

DT[, na.locf(.SD, na.rm=FALSE), by=id]

我发现使用 dplyr 的等效解决方案同样慢。

GRP = DT %>% group_by(id)
data.table(GRP %>% mutate_each(funs(blah=na.locf(., na.rm=FALSE))))

我希望我可以使用 data.table 功能提出滚动的“ self ”联接,但我似乎无法做到正确(我怀疑我需要使用 .N 但我只是还没弄清楚)。

此时我想我必须在 Rcpp 中编写一些内容才能有效地应用分组的 locf。

我是 R 新手,但我对 C++ 并不陌生 - 所以我有信心我能做到。我只是觉得应该有一种有效的方法在 R 中使用 data.table 来做到这一点。

最佳答案

可以通过转发 (cummax) 非 NA 索引 ((!is .na(x)) * seq_along(x)) 并相应地进行子集化:

x = c(1, NA, NA, 6, 4, 5, 4, NA, NA, 2)
x[cummax((!is.na(x)) * seq_along(x))]
# [1] 1 1 1 6 4 5 4 4 4 2

这会使用 na.rm = TRUE 参数复制 na.locf,为了获得 na.rm = FALSE 行为,我们只需要确保 cummax 中的第一个元素为 TRUE:

x = c(NA, NA, 1, NA, 2)
x[cummax(c(TRUE, tail((!is.na(x)) * seq_along(x), -1)))]
#[1] NA NA 1 1 2

在这种情况下,我们不仅需要考虑非 NA 索引,还需要考虑(已排序或待排序)“id”列更改值的索引:

id = c(10, 10, 11, 11, 11, 12, 12, 12, 13, 13)
c(TRUE, id[-1] != id[-length(id)])
# [1] TRUE FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE FALSE

结合以上:

id = c(10, 10, 11, 11, 11, 12, 12, 12, 13, 13)
x = c(1, NA, NA, 6, 4, 5, 4, NA, NA, 2)

x[cummax(((!is.na(x)) | c(TRUE, id[-1] != id[-length(id)])) * seq_along(x))]
# [1] 1 1 NA 6 4 5 4 4 NA 2

请注意,这里我们将第一个元素与 TRUE 进行“或”运算,即使其等于 TRUE,从而得到 na .rm = FALSE 行为。

对于这个例子:

id_change = DT[, c(TRUE, id[-1] != id[-.N])]
DT[, lapply(.SD, function(x) x[cummax(((!is.na(x)) | id_change) * .I)])]
# id aa bb cc
# 1: 1 A NA 1
# 2: 1 A NA 1
# 3: 1 B NA 1
# 4: 1 C NA 1
# 5: 2 NA NA NA
# 6: 2 NA NA 4
# 7: 2 D NA 4
# 8: 2 E NA 5
# 9: 3 F NA 6
#10: 3 F NA 6
#11: 3 F NA 7
#12: 3 F NA 7

关于r - 在单个 R data.table 中按组有效地锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37060211/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com