R data.table有条件地使用另一个data.table中的值替换数据
这与和类似,只是在我的情况下,变量的数量非常大,所以我不想显式地列出它们 我拥有的是一个大的R data.table有条件地使用另一个data.table中的值替换数据,r,data.table,R,Data.table,这与和类似,只是在我的情况下,变量的数量非常大,所以我不想显式地列出它们 我拥有的是一个大的数据表(我们称之为dt_original)和一个较小的数据表(我们称之为dt_newdata),它的ID是第一个的子集,并且只有第一个的一些变量。我想用dt\u newdata中的值更新dt\u original中的值。对于附加的扭曲,我只想有条件地更新值-在本例中,仅当dt_newdata中的值大于dt_original中的相应值时 对于可再现的示例,以下是数据。在现实世界中,表格要大得多: libra
数据表
(我们称之为dt_original
)和一个较小的数据表
(我们称之为dt_newdata
),它的ID是第一个的子集,并且只有第一个的一些变量。我想用dt\u newdata
中的值更新dt\u original
中的值。对于附加的扭曲,我只想有条件地更新值-在本例中,仅当dt_newdata
中的值大于dt_original
中的相应值时
对于可再现的示例,以下是数据。在现实世界中,表格要大得多:
library(data.table)
set.seed(0)
## This data.table with 20 rows and many variables is the existing data set
dt_original <- data.table(id = 1:20)
setkey(dt_original, id)
for(i in 2015:2017) {
varA <- paste0('varA_', i)
varB <- paste0('varB_', i)
varC <- paste0('varC_', i)
dt_original[, (varA) := rnorm(20)]
dt_original[, (varB) := rnorm(20)]
dt_original[, (varC) := rnorm(20)]
}
## This table with a strict subset of IDs from dt_original and only a part of
## the variables is our potential replacement data
dt_newdata <- data.table(id = sample(1:20, 3))
setkey(dt_newdata, id)
newdata_vars <- sample(names(dt_original)[-1], 4)
for(var in newdata_vars) {
dt_newdata[, (var) := rnorm(3)]
}
似乎应该有一种使用连接语法的方法,可能还有前缀
i.
和/或.SD
或类似的东西,但是我尝试过的任何东西都不足以保证在这里重复。根据您的标准,此代码应该以当前格式工作
dt_original[dt_newdata, names(dt_newdata) := Map(pmax, mget(names(dt_newdata)), dt_newdata)]
它连接到data.tables之间匹配的ID,然后使用:=
执行赋值,因为我们想要返回一个列表,所以我使用Map
通过data.tables的列运行pmax
,这些列通过dt_newdata的名称匹配。请注意,所有dt_newdata的名称都必须在dt_原始数据中
在Frank的评论之后,您可以使用[-1]
删除映射
列表项的第一列和列名,因为它们是不需要计算的ID。从Map
中删除第一列可以避免一次通过pmax
,还可以保留id上的密钥。感谢@brian stamper在注释中指出密钥保留
dt_original[dt_newdata,
names(dt_newdata)[-1] := Map(pmax,
mget(names(dt_newdata)[-1]),
dt_newdata[, .SD, .SDcols=-1])]
请注意,
[-1]
的使用假定ID变量位于新数据的第一个位置。如果在别处,您可以手动更改索引或使用grep
根据您的条件,此代码应以当前格式工作
dt_original[dt_newdata, names(dt_newdata) := Map(pmax, mget(names(dt_newdata)), dt_newdata)]
它连接到data.tables之间匹配的ID,然后使用:=
执行赋值,因为我们想要返回一个列表,所以我使用Map
通过data.tables的列运行pmax
,这些列通过dt_newdata的名称匹配。请注意,所有dt_newdata的名称都必须在dt_原始数据中
在Frank的评论之后,您可以使用[-1]
删除映射
列表项的第一列和列名,因为它们是不需要计算的ID。从Map
中删除第一列可以避免一次通过pmax
,还可以保留id上的密钥。感谢@brian stamper在注释中指出密钥保留
dt_original[dt_newdata,
names(dt_newdata)[-1] := Map(pmax,
mget(names(dt_newdata)[-1]),
dt_newdata[, .SD, .SDcols=-1])]
请注意,
[-1]
的使用假定ID变量位于新数据的第一个位置。如果在别处,您可以手动更改索引或使用grep
是的,您的pmax看起来非常像dt_original[dt_newdata,on=(id),pmax(x.varB,i.varB)]
,唯一的问题是坚持将“varB”作为字符传递。。。可能可以通过将数据放在长格式而不是宽格式中来解决。请使用set.seed
使此文件重新生成set.seed(0)
,谢谢。将varB
视为几百个变量名的混合体,是dt\u original
中变量的任意子集。这个例子可能会让它看起来有点太常规了。名称是否异构并不重要。它们显然都是数字的(通过使用pmax来判断),这意味着它们在长格式数据集中的一列中可以很好地协同工作。这就是熔化(dt_original,id=“id”)。从这里开始,您可能还希望将var名称拆分为组件部分…(变量和年份)。如果你对此感兴趣,我建议你看看哈德利关于它的文章:是的,你的pmax看起来很像dtu-original[dtu-newdata,on=(id),pmax(x.varB,I.varB)]
,唯一的问题是坚持将“varB”作为字符传递。。。可能可以通过将数据放在长格式而不是宽格式中来解决。请使用set.seed
使此文件重新生成set.seed(0)
,谢谢。将varB
视为几百个变量名的混合体,是dt\u original
中变量的任意子集。这个例子可能会让它看起来有点太常规了。名称是否异构并不重要。它们显然都是数字的(通过使用pmax来判断),这意味着它们在长格式数据集中的一列中可以很好地协同工作。这就是熔化(dt_original,id=“id”)。从这里开始,您可能还希望将var名称拆分为组件部分…(变量和年份)。如果你对此感兴趣,我建议你看看哈德利的文章:是的,看起来不错。不知道你是否希望它出现在所有栏目中;可能需要排除id
。我想您可能在编辑之前就已经有了它-我正在尝试两种方法,并且使用[-1]
它看起来像pmax
正在尝试将dt_original
的所有行与dt_newdata
进行比较。好的。我返回了原始代码,然后添加了忽略id列的工作代码。有趣的旁注-如果您不跳过ID列,这将消除它是一个键的事实,因此您必须在结果上再次setkey
(如果您想要键控数据)。[-1]
版本保留了密钥。是的,看起来不错。不知道你是否希望它出现在所有栏目中;可能需要排除id
。我想您可能在