如何加速超3000万行数据库中的lapply字符串拆分操作?
优化方案:3000万条字符串高效拆分
核心问题分析
你原代码效率极低的原因是重复执行了4次字符串拆分(每列调用一次strsplit),完全浪费计算资源;同时生成列表列还需要额外转换,进一步拖慢速度。针对大数据量,必须用底层优化的矢量化操作替代循环/重复计算。
最优方案1:用data.table内置tstrsplit(推荐)
tstrsplit是data.table专为字符串拆分设计的矢量化函数,C语言实现,仅需拆分一次即可生成多列普通向量,效率比原方法提升几十倍:
# 拆分v1为4列,直接赋值到原表(原地修改,不复制大表) test[, c("id", "question_id", "answer_id", "answer") := tstrsplit(v1, split = ",", fixed = TRUE, keep = 1:4)] # 可选:将数值型列转换为整数(比字符型更节省内存) test[, `:=`( id = as.integer(id), question_id = as.integer(question_id), answer_id = as.integer(answer_id) )]
fixed = TRUE:因为分隔符是固定逗号,禁用正则匹配,进一步提速keep = 1:4:只保留前4个拆分结果,自动忽略行内多余的分隔字段,完美解决你读取时的字段数不匹配问题- 生成的是普通向量列,无需处理列表类型
最优方案2:读取阶段直接处理(效率更高)
如果你的数据源是文本文件,跳过先读成单列再拆分的步骤,直接用fread的参数处理字段不匹配问题,一步得到目标表:
dt <- fread( "你的数据文件路径.txt", sep = ",", # 指定分隔符 fill = TRUE, # 字段数不匹配时自动补NA select = 1:4, # 只读取前4列,忽略多余字段 col.names = c("id", "question_id", "answer_id", "answer") # 直接指定列名 )
fread是data.table的高速读取函数,底层C实现,读取+拆分的速度远快于先读单列再用R代码拆分,是大数据场景的首选。
为什么原代码慢?
原代码中lapply(strsplit(test$v1, split=","), "[", 1)这类写法,相当于对整个v1列重复拆分4次,3000万条数据的情况下,重复计算带来的时间消耗呈倍数增长;同时lapply生成列表列,后续还要转换为普通向量,进一步增加耗时。
内容的提问来源于stack exchange,提问作者Alejandro Carrera
相关产品推荐
相关产品推荐

