如何在R中将列中逗号分隔值拆分到对应序号列
问卷多选数据按数值匹配列转换
原始数据
df <- data.frame( ID = 1:5, Var = c("3,12,14,15,16,18,20,21", "3,14,20", "3,14,16", "3,12", "3,6,14,15,17,20"), stringsAsFactors = FALSE )
需求说明
需要将Var列中逗号分隔的数值,对应到以Var_XX命名的列中(XX为两位数字序号,从01到21):数值n就放入Var_0n列(n<10时补前导零),未匹配的列填充NA。
已尝试方法及问题
- 使用
str_split_fixed:按逗号拆分后,数值按出现顺序填充到列中,无法对应到序号匹配的列
library(stringr) str_split_fixed(df$Var, ",", 21)
输出结果:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [1,] "3" "12" "14" "15" "16" "18" "20" "21" "" "" "" "" "" "" [2,] "3" "14" "20" "" "" "" "" "" "" "" "" "" "" "" [3,] "3" "14" "16" "" "" "" "" "" "" "" "" "" "" "" [4,] "3" "12" "" "" "" "" "" "" "" "" "" "" "" "" [5,] "3" "6" "14" "15" "17" "20" "" "" "" "" "" "" "" ""
- 使用
cSplit:同样按拆分顺序生成列,不符合序号匹配需求
library(splitstackshape) cSplit(df, "Var", ",")
输出结果:
ID Var_1 Var_2 Var_3 Var_4 Var_5 Var_6 Var_7 Var_8 1: 1 3 12 14 15 16 18 20 21 2: 2 3 14 20 NA NA NA NA NA 3: 3 3 14 16 NA NA NA NA NA 4: 4 3 12 NA NA NA NA NA NA 5: 5 3 6 14 15 17 20 NA NA
目标输出格式
ID Var_01 Var_02 Var_03 Var_04 Var_05 Var_06 Var_07 Var_08 ... Var_21 1: 1 NA NA 3 NA NA NA NA NA ... 21 2: 2 NA NA 3 NA NA NA NA NA ... NA 3: 3 NA NA 3 NA NA NA NA NA ... NA 4: 4 NA NA 3 NA NA NA NA NA ... NA 5: 5 NA NA 3 NA NA 6 NA NA ... NA
解决方案
方法1:使用tidyverse工具链(推荐,适合学习)
利用tidyr的separate_rows将长字符串拆分成行,再用pivot_wider将行转换为对应序号的列,最后补全所有需要的列并排序。
library(tidyverse) # 1. 拆分Var列为多行,生成规范列名 df_long <- df %>% separate_rows(Var, sep = ",") %>% mutate( Var = as.integer(Var), col_name = str_glue("Var_{str_pad(Var, 2, pad = '0')}") ) # 2. 转换为宽格式,填充NA df_wide <- df_long %>% pivot_wider( id_cols = ID, names_from = col_name, values_from = Var, values_fill = NA_integer_ ) # 3. 补全Var_01到Var_21的所有列,确保无遗漏 all_cols <- str_glue("Var_{str_pad(1:21, 2, pad = '0')}") df_final <- df_wide %>% select(ID, all_of(all_cols)) # 查看结果 print(df_final)
方法2:基础R实现
通过创建空矩阵,循环填充对应位置的值,适合理解底层逻辑。
# 初始化结果矩阵:行数为df的行数,列数21,填充NA result_matrix <- matrix(NA_integer_, nrow = nrow(df), ncol = 21) colnames(result_matrix) <- sprintf("Var_%02d", 1:21) # 循环每一行,填充对应位置 for(i in 1:nrow(df)){ # 拆分当前行的Var值为整数向量 vals <- as.integer(strsplit(df$Var[i], ",")[[1]]) # 数值n对应第n列,填充值 result_matrix[i, vals] <- vals } # 转换为数据框,合并ID列 df_final <- cbind(df$ID, as.data.frame(result_matrix)) colnames(df_final)[1] <- "ID" # 查看结果 print(df_final)
说明
- tidyverse方法简洁易读,适合日常数据处理;基础R方法能帮助理解数据结构转换逻辑,适合学习阶段深入掌握。
- 拆分后需将数值转换为整数类型,避免字符串类型导致的索引错误。
内容的提问来源于stack exchange,提问作者MMc
相关产品推荐
相关产品推荐

