在dplyr中从空格分隔字符串提取指定位置后段的高效方法
高效提取指定位置后续音素的解决方案
我来帮你搞定这个大数据量下的音素提取问题——10万行数据用循环确实效率拉胯,咱们换向量化的方案来提速,先看看你之前dplyr写法报错的原因,再给你几个高效的实现方式:
为什么你的dplyr代码报错?
你之前写的这段代码:
data <- data %>% mutate(fol.seg = word.segs %>% strsplit(split = " ") %>% unlist() %>% nth(seg.index+1))
问题出在strsplit(word.segs, " ") %>% unlist()会把所有行的音素拆成一个超大的一维向量,然后nth(seg.index+1)试图用一整列的索引值去提取,但nth()只能接受单个位置参数,自然就报length(n) == 1 is not TRUE的错误了。咱们需要对每行单独处理,而不是把所有音素揉在一起提取。
高效解决方案推荐
下面三个方案都是向量化操作,完全避免循环,适合10万行级别的数据:
方案1:tidyverse组合(直观易读)
用tidyr的separate_rows先把音素拆成行,标记位置后再匹配回原数据:
library(dplyr) library(tidyr) # 给每行加唯一ID,方便后续合并 data <- data %>% mutate(row_id = row_number()) # 拆分音素并标记每个音素的位置 seg_details <- data %>% separate_rows(word.segs, sep = " ") %>% group_by(row_id) %>% mutate(seg_pos = row_number()) %>% ungroup() # 匹配seg.index+1和seg.index+2的音素,合并回原数据 result <- data %>% left_join( seg_details %>% filter(seg_pos == seg.index + 1) %>% select(row_id, fol.seg = word.segs), by = "row_id" ) %>% left_join( seg_details %>% filter(seg_pos == seg.index + 2) %>% select(row_id, fol.seg2 = word.segs), by = "row_id" ) %>% select(-row_id) # 移除临时ID列
方案2:purrr+stringr(简洁灵活)
用str_split把每行音素拆成列表,再用map_chr对应每行提取指定位置的元素,还能处理索引超出范围的情况(返回NA):
library(dplyr) library(stringr) library(purrr) data <- data %>% mutate( # 把每行音素拆成列表 seg_list = str_split(word.segs, " "), # 提取seg.index+1的音素,超出范围返回NA fol.seg = map_chr(seq_along(seg_list), ~ seg_list[[.]][seg.index[.] + 1] %||% NA_character_), # 提取seg.index+2的音素,超出范围返回NA fol.seg2 = map_chr(seq_along(seg_list), ~ seg_list[[.]][seg.index[.] + 2] %||% NA_character_) ) %>% select(-seg_list) # 移除临时列表列
这里的%||%是purrr的工具函数,专门用来处理“如果左边是NULL/不存在,就返回右边值”的场景,避免索引越界报错。
方案3:data.table(速度最快,适合超大数据)
如果追求极致速度,data.table的原地修改操作能把效率拉满,特别适合10万+行的数据:
library(data.table) # 把data.frame转成data.table setDT(data) # 原地新增fol.seg和fol.seg2列 data[, c("fol.seg", "fol.seg2") := { seg_list = strsplit(word.segs, " ") list( sapply(seq_along(seg_list), function(i) seg_list[[i]][seg.index[i]+1] %||% NA_character_), sapply(seq_along(seg_list), function(i) seg_list[[i]][seg.index[i]+2] %||% NA_character_) ) }]
内容的提问来源于stack exchange,提问作者Iarwain
相关产品推荐
相关产品推荐

