如何为dplyr的separate函数添加排序属性规整多选问卷数据
问题:如何规整多选问卷拆分后的结果列顺序?
我有一份“可多选”问卷的数据,格式如下:
ID <- c(1,2,3,4,5) answer <- c("apple, orange", "pinneaple, apple", "orange, pinneaple", "pinneaple, orange","apple") df <- data.frame(ID,answer) > df ID answer 1 1 apple, orange 2 2 pinneaple, apple 3 3 orange, pinneaple 4 4 pinneaple, orange 5 5 apple
我尝试用dplyr包的separate函数拆分并展开结果,但只实现了部分需求:
df %>% separate(answer, into = c("ans1", "ans2","ans3"), sep = ", ") > df ID ans1 ans2 ans3 1 1 apple orange <NA> 2 2 pinneaple apple <NA> 3 3 orange pinneaple <NA> 4 4 pinneaple orange <NA> 5 5 apple <NA> <NA>
我希望将结果按指定顺序规整,比如让ans1对应apple,最终得到如下目标数据框:
> target_df ID ans1 ans2 ans3 1 1 apple orange <NA> 2 2 apple <NA> pinneaple 3 3 <NA> orange pinneaple 4 4 <NA> orange pinneaple 5 5 apple <NA> <NA>
请问能否为separate函数添加该排序属性?
解决方案:separate本身不支持排序属性,但可通过后续步骤实现目标
separate的核心作用只是按分隔符拆分字符串,没有内置的排序/规整列内容的功能。不过可以通过两种思路实现你的需求:
方法一:长格式转换法(推荐,适配复杂场景)
先把拆分后的内容转成长格式,再按指定选项顺序转回宽格式,确保每个选项对应固定列:
library(dplyr) library(tidyr) # 定义目标列对应的选项顺序:ans1→apple,ans2→orange,ans3→pinneaple target_order <- c("apple", "orange", "pinneaple") df %>% # 将每个选项拆分为单独行 separate_rows(answer, sep = ", ") %>% # 为每个选项匹配对应的目标列名 mutate(col = paste0("ans", match(answer, target_order))) %>% # 转回宽格式,空值填充NA pivot_wider( id_cols = ID, names_from = col, values_from = answer, values_fill = NA ) %>% # 强制列顺序符合目标要求 select(ID, paste0("ans", seq_along(target_order)))
运行结果:
# A tibble: 5 × 4 ID ans1 ans2 ans3 <dbl> <chr> <chr> <chr> 1 1 apple orange NA 2 2 apple NA pinneaple 3 3 NA orange pinneaple 4 4 NA orange pinneaple 5 5 apple NA NA
方法二:行内排序法(适合小数据量)
在separate拆分后,直接对每行的选项按指定顺序排序,再重新赋值到对应列:
library(dplyr) library(tidyr) library(purrr) target_order <- c("apple", "orange", "pinneaple") df %>% separate(answer, into = c("ans1", "ans2", "ans3"), sep = ", ", fill = "right") %>% rowwise() %>% mutate( # 提取当前行的有效选项,匹配目标顺序的位置并排序 sorted_pos = list(sort(match(c(ans1, ans2, ans3), target_order), na.last = NA)), # 按排序后的位置给对应列赋值 ans1 = ifelse(1 %in% sorted_pos, target_order[1], NA), ans2 = ifelse(2 %in% sorted_pos, target_order[2], NA), ans3 = ifelse(3 %in% sorted_pos, target_order[3], NA) ) %>% select(-sorted_pos) %>% ungroup()
该方法同样能得到符合要求的目标数据框。
内容的提问来源于stack exchange,提问作者Unai Vicente
相关产品推荐
相关产品推荐

