使用tidyr::separate_rows拆分不等长行时删除postcodes列多余字符串
实现方法
核心逻辑是在拆分长表前,逐行将postcodes列拆分后的元素长度截断为和同行suburb拆分后一致的长度,再统一调用tidyr::separate_rows做拆分,即可自动丢弃多余的邮编值,避免拆分后错位、值不匹配的问题。
首先修正你提供的示例代码中存在的赋值符号误用、引号不配对问题,可复现的测试数据如下:
library(tidyr) library(dplyr) library(stringr) Df <- data.frame( Id = c(1, 2, 3), suburb = c('orange, yellow', 'blue', 'green, yellow'), postcodes = c('a9, b9', 'c9, a9, b9', 'd9, b9, a9'), stringsAsFactors = FALSE )
推荐实现(提前截断,无错位风险)
result <- Df %>% rowwise() %>% mutate( # 计算当前行suburb拆分后的元素个数,作为长度基准 ref_len = length(str_split(suburb, ",\\s*", simplify = TRUE)), # 拆分postcodes后仅保留前ref_len个元素,重新拼接为字符串 postcodes = str_split(postcodes, ",\\s*")[[1]][1:ref_len] %>% str_c(collapse = ", ") ) %>% ungroup() %>% # 两列拆分长度已完全对齐,直接拆分为多行 separate_rows(c(suburb, postcodes), sep = ",\\s*")
关键参数说明:
- 分隔符使用
",\\s*"可兼容逗号后带0到多个空格的情况,避免拆分出带多余空白的元素 - 截断逻辑自动适配每一行的基准长度:如示例中Id=2的行suburb仅1个值,postcodes拆分后有3个值,会自动保留第一个邮编
c9,丢弃后2个多余值;Id=3的行suburb有2个值,postcodes拆分后有3个值,会自动保留前2个邮编d9、b9,丢弃最后1个多余值
运行后输出结果:
# A tibble: 5 × 3 Id suburb postcodes <dbl> <chr> <chr> 1 1 orange a9 2 1 yellow b9 3 2 blue c9 4 3 green d9 5 3 yellow b9
备选实现(拆分后过滤)
如果不想提前处理字符串,也可以先拆分两列再按组过滤多余行:
result_alt <- Df %>% separate_rows(suburb, sep = ",\\s*") %>% separate_rows(postcodes, sep = ",\\s*") %>% group_by(Id) %>% filter(row_number() <= sum(!is.na(suburb))) %>% ungroup()
注意:该方案因为对两列独立做拆分,当字段内分隔符分布不规则时容易出现suburb和postcodes值错位的问题,优先使用提前截断的实现方案。
内容的提问来源于stack exchange,提问作者lenlen
相关产品推荐
相关产品推荐

