如何使用R语言tidyverse将带分隔符字符串拆分为虚拟变量
R tidyverse 实现分号分隔多选结果转0-1宽表的简洁方案
这个场景不需要写繁琐的逐选项判断逻辑,用tidyr的两个核心函数就能链式完成全流程,全程不需要硬编码答案选项,后续新增选项也能自动适配。
首先加载tidyverse并构造示例原始数据:
library(tidyverse) raw_df <- tibble( Person = c("Matt", "Sandy", "Charles"), Answer = c("A;B;C;", "B;D;", "A;C;D;") )
核心转换代码如下:
wide_df <- raw_df |> # 按分号分隔符将多选答案拆为长格式,单个选项对应一行 separate_longer_delim(Answer, delim = ";") |> # 过滤掉字符串末尾分号拆分出的空值,不需要提前做字符串截断清洗 filter(Answer != "") |> # 长表转宽表,自动生成所有选项列,选中记1、未选中记0 pivot_wider( names_from = Answer, values_from = Answer, # 直接用计数函数生成选中标记,不需要额外mutate新建值为1的辅助列 values_fn = length, # 未出现的选项自动填充0 values_fill = 0 )
若使用的tidyr版本低于1.3.0,将
separate_longer_delim(Answer, delim = ";")替换为separate_rows(Answer, sep = ";")即可,逻辑完全一致。
运行后得到的结果完全匹配需求:
| Person | A | B | C | D |
|---|---|---|---|---|
| Matt | 1 | 1 | 1 | 0 |
| Sandy | 0 | 1 | 0 | 1 |
| Charles | 1 | 0 | 1 | 1 |
常见冗余操作说明
很多人实现时觉得步骤繁琐,通常是两个多余操作导致的:
- 拆分前额外写正则去掉Answer列末尾的分号,实际上拆分后直接过滤空字符串更省事
- 拆分后额外mutate生成一个值恒为1的标记列再做宽表转换,其实
pivot_wider自带的values_fn参数可以直接完成计数标记,省掉新建列的步骤
如果答案选项存在固定顺序要求,可以在转完宽表后用relocate()调整列顺序即可,不需要改动核心转换逻辑。
内容的提问来源于stack exchange,提问作者Em Rushworth
相关产品推荐
相关产品推荐

