使用另一个data.table中的值更新data.table中的值

时间:2017-02-26 13:19:22

标签: r data.table

我有一个大约有2500万行的数据集。我正在获取这些行的子集并执行一个工作正常的函数。但是,我需要做的是使用新值更新原始数据集中的值,同时保留其余值。我确信这很简单,但我无法理解它。

这是我正在处理的简化版本:

require("data.table")

df <-data.frame(AREA_CD = c(sample(1:25000000, 25000000, replace=FALSE)), ALLOCATED = 0, ASSIGNED = "A", ID_CD = c(1:25000000))
df$ID_CD <- interaction( "ID", df$ID_CD, sep = "")
dt <- as.data.table(df)

sub_dt <- dt[5:2004,]
sub_dt[,ALLOCATED:=ALLOCATED+1]
sub_dt[,ASSIGNED:="B"]

我所追求的是来自sub_dt的'ALLOCATED'和'ASSIGNED'中的值,以根据'ID_CD'列替换dt中的'ALLOCATED'和'ASSIGNED'值。根据我的例子,我想要的输出仍然有2500万行,但有2,000行更新。任何帮助将非常感激。感谢。

1 个答案:

答案 0 :(得分:2)

David Arenburg提供的答案in his comment解释了如何将修改后的数据子集重新加入原始data.table

但是,我想知道OP为什么不使用返回列表的函数直接在原始data.table 中通过引用应用更改:

my_fun <- function(alloc, assig) {
  list(
    alloc + 1,
    "B")
}

使用此功能,可以在data.table

中直接更新行的子集
dt[5:2004, c("ALLOCATED", "ASSIGNED") := my_fun(ALLOCATED, ASSIGNED)]
dt[1:7]
#   AREA_CD ALLOCATED ASSIGNED ID_CD
#1:    1944         0        A   ID1
#2:    3265         0        A   ID2
#3:   15415         0        A   ID3
#4:   14121         0        A   ID4
#5:   10546         1        B   ID5
#6:    2263         1        B   ID6
#7:   12339         1        B   ID7

基准

由于内存限制,只使用了250万行(而不是OP中的2500万行)的较小数据集。

library(microbenchmark)
setDT(df)  # coerce df to data.table
microbenchmark(
  copy = dt <- copy(df),
  join = {
    dt <- copy(df)
    sub_dt <- dt[5:2004,]
    sub_dt[,ALLOCATED:=ALLOCATED+1]
    sub_dt[,ASSIGNED:="B"]
    dt[sub_dt, `:=`(ALLOCATED = i.ALLOCATED, ASSIGNED = i.ASSIGNED), on = .(ID_CD)]
  },
  byref = {
    dt <- copy(df)
    dt[5:2004, c("ALLOCATED", "ASSIGNED") := my_fun(ALLOCATED, ASSIGNED)]
  },
  times = 10L
)
#Unit: milliseconds
#  expr       min        lq      mean    median        uq       max neval
#  copy  13.80400  14.07850  28.22882  14.15836  14.39643 154.70570    10
#  join 239.36476 240.72745 244.27668 243.52967 246.17104 255.06271    10
# byref  14.28806  14.47308  15.00056  14.63147  14.73134  18.71181    10

更新data.table&#34;到位&#34;比创建子集和以后加入要快得多。需要复制操作才能使用未修改版本的dt启动每个基准测试运行。因此,复制操作也是基准测试。

使用

data.table版本1.10.4。