我有一个非常长的表,其中的数据以R表示,其中包含一些键列和一个查找表,其中包含相同的键列和一些额外的变量.我想从查找表中 Select 基于相同键的子集,并通过对公共变量进行内插来填充数据表中的新列.

我试着举一个简单的例子:

library(data.table)
data <- data.table(A = c("A","A","A","B","B","B","C","C","C"),
                   B = c(1,1,1,1,1,1,2,2,2),
                   C = rep(c(0.15, 0.22, 0.3),3))
data
#    A B    C
# 1: A 1 0.15
# 2: A 1 0.22
# 3: A 1 0.30
# 4: B 1 0.15
# 5: B 1 0.22
# 6: B 1 0.30
# 7: C 2 0.15
# 8: C 2 0.22
# 9: C 2 0.30

look <- data.table(A = c("A","A","A","B","B","B","C","C","C"),
                   B = c(1,1,1,1,1,1,2,2,2),
                   C = rep(c(0.1, 0.2, 0.3),3),
                   D = c(10, 20, 30, 11,22,33,12,24,36))
look
#    A B   C  D
# 1: A 1 0.1 10
# 2: A 1 0.2 20
# 3: A 1 0.3 30
# 4: B 1 0.1 11
# 5: B 1 0.2 22
# 6: B 1 0.3 33
# 7: C 2 0.1 12
# 8: i 2 0.2 24
# 9: C 2 0.3 36

我想要一个匹配的AB列使用look$Clook$D,并创建一个新的data$D列通过插值的基础上data$C.

我有一个for循环,对于每个匹配的A、B组合,它从look次运行f <- approxfun(look$C, look$D)创建一个子集matched并应用它data[ A == 'A' & B == 1, D := f(C) ].

所以在一次迭代中会是这样的

f <- approxfun(c(0.1, 0.2, 0.3), c(10, 20, 30) )
f(c(0.15, 0.22, 0.3))
## and the data table will become
data
#    A B    C  B
# 1: A 1 0.15 15
# 2: A 1 0.22 22 
# 3: A 1 0.30 30
# 4: B 1 0.15
# 5: B 1 0.22
# 6: B 1 0.30
# 7: C 2 0.15
# 8: C 2 0.22
# 9: C 2 0.30

问题是nrow(DATA) > 6000000nrow(look) > 20000,必须为3个新列完成,迭代已经运行了一天多.因此,我需要一种更有效的方法.

也许有一种更好的data.tabledlpyr的方法,但我还没有想好.

在一些背景下:

在我的领域,这是常见的做法,与观察和等效建模值,用于参考.我们可以 for each 观察值或一系列值运行一个模型.观测值和模型之间的一些常见变量可能是精确的,希望只有一个足够接近,并且可以从建模值插值.

在这种情况下,我使用的是一个分辨率为1分钟的30年数据集,当前可用的观测值是&gt;6000000.目前,模型值只是每月的气候变化&gt;27000.在future ,我预计模型值将会更多,时间步长会更细,因此匹配和内插问题将是分析中的一大瓶颈.

解决方案:

@thothal方法给了我确切的结果作为我的第一个方法,与迭代判断.但是,我的数据很复杂,也许我在实现中遗漏了一些东西.从~2小时,我得到了只是几秒钟!感谢大家的建议,你给了我一些非常有用的见解,这类问题.

推荐答案

让我来介绍一下data.table%的解决方案:

## 1. Create an `approxfun` for each `A/B` combination

## The + 0 trick is necessary b/c otherwise data.table does not evaluate C, D
## while creation and thus keeps just the last chunk of it 

(fns <- look[, .(f = list(approxfun(C + 0, D + 0))), .(A, B)])
#    A B             f
# 1: A 1 <function[1]>
# 2: B 1 <function[1]>
# 3: C 2 <function[1]>

## 2. Join it to data and apply the function
data[fns, .(A, B, C, D = Map(\(f, x) f(x), f, C)), on = .(A, B)]
#    A B    C    D
# 1: A 1 0.15   15
# 2: A 1 0.22   22
# 3: A 1 0.30   30
# 4: B 1 0.15 16.5
# 5: B 1 0.22 24.2
# 6: B 1 0.30   33
# 7: C 2 0.15   18
# 8: C 2 0.22 26.4
# 9: C 2 0.30   36

## w/o Map you would do:
## data[fns, on = .(A, B)][, .(C, f[[1]](C)), .(A, B)]

诚然,+ 0的把戏很难看,如果有人知道一个更规范的方法来解决它,我很高兴听到,b/c省略它不会起作用(最有可能是b/c的懒惰判断):

data[look[, .(f = list(approxfun(C, D))), .(A, B)], 
     .(A, B, C, D = Map(\(f, x) f(x), f, C)), on = .(A, B)]
#    A B    C    D
# 1: A 1 0.15   18 <<- always approxfun(c(.1, .2, .3), c(12, 24, 26))
# 2: A 1 0.22 26.4
# 3: A 1 0.30   36
# 4: B 1 0.15   18
# 5: B 1 0.22 26.4
# 6: B 1 0.30   36
# 7: C 2 0.15   18
# 8: C 2 0.22 26.4
# 9: C 2 0.30   36

R相关问答推荐

基于不同组的列的相关性

使用tidy—select创建一个新的带有mutate的摘要变量

如何改变时间图R中的悬停信息?

如何计算多个日期是否在一个日期范围内

用关联字符串替换列名的元素

使用较长的查询提取具有部分匹配的列表中的较短目标,

打印XTS对象

ComplexHEAT:使用COLUMN_SPLIT时忽略COLUMN_ORDER

以字符格式导入的ExcelElectron 表格日期列标题

当我添加美学时,geom_point未对齐

将多个列合并为一个列的有效方法是什么?

向R中的数据帧添加一列,该列统计另一列中每个唯一值的二进制观测值的数量

整理曲线图、曲线图和点图

如何将宽格式的患者信息数据高效地转换为患者计数的时间序列?

我正在try 创建一个接近cos(X)的值的While循环,以便它在-或+1-E10范围内

如何更改包中函数中的参数?

将y轴格式更改为R中的百分比

如何将两个用不同的运算符替换*的矩阵相乘

在shiny /bslb中,当卡片是从json生成时,如何水平排列卡片?

当y为负值时,无法使stat_cor正确定位到底部?