如何用Base R实现与separate_rows一致的多列拆分多行效果?
用Base R实现与tidyr::separate_rows一致的多列字符串拆分效果
你之前的Base R代码得到38行的原因是expand.grid会对拆分后的列元素生成笛卡尔积(所有可能的组合),而separate_rows是按位置一一对应拆分:同一行中name的第n个元素对应surname的第n个元素,非拆分列(code、number)重复对应次数,最终行数是各行拆分后元素的长度之和(4+3+2+3=12)。
实现代码
# 定义需要拆分的列 cols_to_split <- c("name", "surname") # 逐行处理并合并结果 split_result <- do.call(rbind, lapply(seq_len(nrow(test)), function(i) { # 获取当前行数据 row <- test[i, , drop = FALSE] # 拆分指定列,兼容带空格的分隔符(如"; ") split_cols <- lapply(row[cols_to_split], function(x) { strsplit(as.character(x), " *; *")[[1]] }) # 校验拆分后各列长度一致(与separate_rows行为对齐,不一致则报错) col_lengths <- sapply(split_cols, length) if (length(unique(col_lengths)) != 1) { stop("同一行内待拆分列拆分后长度不一致") } # 重复非拆分列的值,匹配拆分后的元素数量 non_split_cols <- row[, !names(row) %in% cols_to_split, drop = FALSE] non_split_repeated <- non_split_cols[rep(1, col_lengths[1]), , drop = FALSE] # 组合所有列并返回 cbind(non_split_repeated, as.data.frame(split_cols)) }))
验证结果
运行后查看行数,与separate_rows结果一致:
nrow(split_result) # 输出12
代码逻辑说明
- 用
lapply逐行处理,避免apply将数据框转为矩阵导致的类型异常; - 拆分指定列时,用
" *; *"作为分隔符,兼容分号前后带空格的情况; - 校验拆分后列长度一致,与
separate_rows的报错行为对齐; - 非拆分列按拆分后元素长度重复,保证与拆分列的元素一一对应,而非生成笛卡尔积。
内容的提问来源于stack exchange,提问作者i.b
相关产品推荐
相关产品推荐

