【问题标题】:Assignment via `:=` in a for loop (R data.table)在 for 循环中通过 `:=` 赋值(R data.table)
【发布时间】:2015-06-09 02:11:40
【问题描述】:

我正在尝试在 for 循环中分配一些新变量(我正在尝试创建一些具有通用结构的变量,但这些变量取决于子样本)。

我一生都在尝试在示例数据上重现此错误,但我做不到。这是有效的代码,并获得了我想做的事情的要点:

DT <- data.table(
  id = rep(1:100, each = 20L),
  period = rep(-9:10, 100L),
  grp = rep(sample(4L, size = 100L, replace = TRUE), each = 20L),
  y = runif(2000, min=0, max=5), key = c("id", "period")
)
DT[ , x := cumsum(y), by = id]
DT2 <- DT[id %in% seq(1, 100, by=2)]
DT3 <- DT[id %in% seq(1, 100, by=3)]

for (dd in list(DT, DT2, DT3)){
  setkey(setkey(dd, grp)[dd[period==0, sum(x), by = grp], x_at_0_by_grp := V1], id, period)
}

这很好用——但是,当我对自己的代码执行此操作时,它会生成 Invalid .internal.selfref 警告(并且不会创建我想要的变量):

[.data.table(setkey(dt, 治疗), dt[posting_rel == 0, sum(current_balance), : 检测到无效的 .internal.selfref 并且 通过复制 整个表,以便 := 可以通过引用添加此新列。晒黑 早些时候,这个 data.table 已被 R 复制(或已创建 手动使用结构()或类似)。避免 keyv3.0.2 如果那是咬人的话。如果此消息没有帮助,请 向 datatable-help 报告,以便修复根本原因。

事实上,当我将我的数据子集在合并中需要的那些列时,它也适用于我的数据(尽管不会保存到原始数据集)。

这向我表明这是一个键控问题,但我在每一步都明确设置键。我完全不知道如何从这里调试它,因为除了我的完整数据集外,我无法重复出现错误。

如果我将操作分解为步骤,则在合并步骤会出现错误:

for (dd in list(DT, DT2, DT3)){
  dummy <- dd[period==0, sum(x), by = grp]
  setkey(dd, grp)
  dd[dummy, x_at_0_by_grp := V1] #***ERROR HERE***
  setkey(dd, id, period)
}

快速更新——如果我使用lapply 而不是在for 循环中进行转换,也会产生错误。

你知道这里到底发生了什么吗?


更新:我想出了一个解决方法:

nnames <- c("dt", "dt2", "dt3")

dt_list <- list(DT, DT2, DT3)

for (ii in 1:3){
  dummy <- copy(dt_list[[ii]])
  dummy[ , x_at_0_by_grp := sum(x[period == 0]), by=grp]
  assign(nnames[ii], dummy)
}

仍然想了解发生了什么,也许是在这种情况下迭代分配变量的更好方法。

【问题讨论】:

  • 我对您的错误没有任何解释,但您可以考虑将这些数据合并到一个 data.table 中并使用它。 DT &lt;- rbindlist(list(dt[,src:=1],dt2[,src:=2],dt3[,src:=3]))即使你不想堆叠数据,你的第二步也不需要合并,只需使用sum(x[period==0]) ... DT[,x_at_0_by_grp:=sum(x[period==0]),by="src,grp"]
  • 感谢您提供避免合并的提示,我没有想到这一点。但是,错误仍然存​​在——向我暗示问题是循环遍历data.tablelist 调用(在涉及Invalid .internal.selfref 的其他问题中提到的麻烦)和使用:= 运算符的组合,而不是合并本身。
  • 另外,我不希望合并数据,因为 1)每个子集都有约 300,000 个观察值,2)我可以在我的主要数据集中定义您的 src 作为子样本包含的指标,但是子样本特定变量的数量意味着我必须在原始数据集中保留 20-30 个具有子样本特定名称的变量——循环使用变量名称一致的数据集感觉更自然。
  • 嗯,奇怪的是copy 成功了;我认为您可以将其发布为答案。是的,我明白你为什么不想像那样堆叠数据集。无论如何,我已经发布了我的下一个建议作为答案,因为它太长了。
  • 同样的做法,但这个 ex 不警告 `` iris

标签: r data.table


【解决方案1】:

对于 20-30 个条件,将它们保留在列表之外(使用手动名称,如 dt2 等)太笨拙了,所以我假设您将它们全部放在 dt_list 中。

我建议只使用您正在计算的统计数据制作表格,然后rbinding 他们:

xxt <- rbindlist(lapply(1:length(dt_list),function(i) 
         dt_list[[i]][,list(cond=i,xx=sum(x[period==0])),by=grp]))

创造

    grp cond       xx
 1:   1    1 623.3448
 2:   2    1 784.8438
 3:   4    1 699.2362
 4:   3    1 367.7196
 5:   1    2 323.6268
 6:   4    2 307.0374
 7:   2    2 447.0753
 8:   3    2 185.7377
 9:   1    3 275.4897
10:   4    3 243.0214
11:   2    3 149.6041
12:   3    3 166.3626

如果你真的想要这些变量,你可以很容易地合并回来。例如,对于dt2

myi = 2
setkey(dt_list[[myi]],grp)[xxt[cond==myi,list(grp,xx)]]

这并不能解决您遇到的错误,但我认为这是一种更好的方法。

【讨论】:

  • 我喜欢这个。两个问题:1)某些条件不是由任何子组完成的——例如,一个变量是x 的四分位数(使用cut 完成),因此单独存储它需要与原始表一样多的行; 2) 如果我想合并 xxt 的所有内容(我会这样做——我最终会使用这些变量作为控制来运行回归,所以将所有变量放在同一个 data.table 中并设置 ,data=dt 会更简洁),看来我将再次需要一个 for 循环,这表明我会遇到同样的问题(尚未测试),除非它真的只是 := 的问题。
  • 我的预感是 := 中的一个错误。听起来您有一个相当复杂的程序;我不知道如何解决这两个问题。
猜你喜欢
  • 2023-03-14
  • 1970-01-01
  • 2016-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-01
  • 2023-04-09
相关资源
最近更新 更多