在pivot_longer中引用函数参数作为列名的问题
解决用函数拆分逗号分隔列并保留原列名的问题
问题分析
你需要实现一个函数,将指定的逗号分隔字符串列拆分成多行,同时保留原列名。原代码存在以下问题:
- 使用
cSplit_e生成多列再转长,步骤冗余且易出错 - 未正确处理tidyeval逻辑,导致列名被替换成参数名
questionID - 引用了不存在的列
deid_pat_id(原数据中实际为record) - 未正确过滤空字符串对应的行
简化解决方案
使用tidyr::separate_rows可直接实现拆分逗号分隔字符串到行的需求,配合tidyeval的{{}}语法能正确传递列名参数,步骤更简洁高效:
完整代码
library(tidyverse) # 构建原始数据集 record <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) x214532 <- c("shirts, shoes", "shoes, purses, hats", "shirts, shoes, hats, heavy machinery", "sponges, shoes", "hats, heavy machinery", "", "heavy machinery, purses, shirts", "heavy machinery, shoes, sponges", "sponges", "shoes") screening_data_responses_char <- data.frame(record, x214532) # 定义拆分函数 deconcatenate <- function(data, questionID) { data %>% # 拆分逗号(兼容逗号后带空格的情况) separate_rows({{questionID}}, sep = ",\\s*") %>% # 过滤空字符串行 filter({{questionID}} != "") } # 调用函数生成长格式数据 screening_data_long <- deconcatenate(screening_data_responses_char, x214532) # 查看结果示例 head(screening_data_long)
运行结果
record x214532 1 1 shirts 2 1 shoes 3 2 shoes 4 2 purses 5 2 hats 6 3 shirts
关键说明
separate_rows的优势:专门用于将单个列的分隔字符串拆分成多行,自动保留其他列的对应值,无需手动生成多列再转长,逻辑更直观。- tidyeval语法
{{}}:在函数中用{{questionID}}引用参数,能正确将传入的列名(如x214532)识别为数据框的列,避免列名被替换成参数名questionID。 - 兼容空格的分隔符:
sep = ",\\s*"可以匹配逗号后带任意空格的情况,确保拆分后的字符串没有多余空格。 - 过滤空行:通过
filter({{questionID}} != "")去掉原数据中空字符串对应的无效行。
若坚持使用pivot_longer的实现方式
如果一定要用pivot_longer,可先将字符串拆分到列表列,再展开:
deconcatenate_pivot <- function(data, questionID) { data %>% mutate({{questionID}} := str_split({{questionID}}, ",\\s*")) %>% unnest({{questionID}}) %>% filter({{questionID}} != "") } # 调用函数 screening_data_long_pivot <- deconcatenate_pivot(screening_data_responses_char, x214532)
这个方法同样能实现需求,但separate_rows的写法更简洁直接。
内容的提问来源于stack exchange,提问作者Catherine
相关产品推荐
相关产品推荐

