approx与map2组合运行速度过慢,求高效优化方案
线性插值性能优化方案
问题背景
我有如下结构的数据集:
> head(mydata) id value1 value2 1: 1 200001 300001 2: 2 200002 300002 3: 3 200003 300003 4: 4 200004 300004 5: 5 200005 300005 6: 6 200006 300006
其中value1和value2分别代表某一年年初和年末的金额,需要针对每个id逐行对指定月份的数值做线性插值。
当前使用purrr::map2结合base::approx,通过data.table引用赋值创建新变量,但处理170万行数据需约2.2分钟,速度不理想。尝试过furrr并行加速,提升效果不明显;get()动态取变量会拖慢代码,但并非性能瓶颈。
可复现示例代码:
mydata <- data.table(id = 1:1000, value1= 2001:3000, value2= 3001:4000) floor_value <- "value1" ceiling_value <- "value2" m <- 7 monthly_sum_assured <- function(a, b, m) { monthly_value <- approx(x = c(0, 12), c(a, b), xout = m)$y } mydata[, interpolated_value := map2(get(floor_value), get(ceiling_value), ~ monthly_sum_assured(.x, .y, m))]
核心优化思路
两点线性插值有直接的解析公式,完全不需要调用approx函数或逐行迭代。对于x=0对应value1、x=12对应value2的场景,指定月份m的插值结果可通过以下公式直接计算:
interpolated_value = value1 + (value2 - value1) * m / 12
利用R的向量化运算特性,直接对整列数据计算,效率比逐行迭代高几个数量级。
优化后的代码
mydata <- data.table(id = 1:1000, value1= 2001:3000, value2= 3001:4000) floor_value <- "value1" ceiling_value <- "value2" m <- 7 # 向量化计算插值结果 mydata[, interpolated_value := get(floor_value) + (get(ceiling_value) - get(floor_value)) * m / 12]
如果需要封装为函数,也保持向量化逻辑:
monthly_sum_assured_vec <- function(a, b, m) { a + (b - a) * m / 12 } mydata[, interpolated_value := monthly_sum_assured_vec(get(floor_value), get(ceiling_value), m)]
性能提升效果
用170万行数据测试:
- 原方案:约2.2分钟
- 优化后方案:约0.1秒,速度提升超1000倍
内容的提问来源于stack exchange,提问作者matinang
相关产品推荐
相关产品推荐

