如何按行判断条件,提取仅选单种最爱水果的受访者选择值?
解决方案:生成单一最爱水果的因子变量
方法1:dplyr + tidyr 方案(避免重复行)
不用复杂转置,先筛选选中的水果,再按受访者ID判断是否仅选了一种:
library(dplyr) library(tidyr) df <- df %>% # 计算每行选中的水果数量 mutate(selected_count = rowSums(!is.na(pick(starts_with("fav_"))))) %>% # 只保留选中的水果记录(自动丢弃未选的NA行) pivot_longer(cols = starts_with("fav_"), names_to = "fruit", values_drop_na = TRUE) %>% # 去掉水果名里的"fav_"前缀 mutate(fruit = sub("fav_", "", fruit)) %>% # 按ID分组,仅选一种的保留水果名,否则设为NA group_by(id) %>% mutate(fav_fruit = if (n() == 1) first(fruit) else NA_character_) %>% # 转回宽格式,每个ID只留一行 pivot_wider(id_cols = c(id, selected_count), values_from = fav_fruit, values_fill = NA) %>% ungroup() %>% # 和原数据合并,确保所有受访者都在 right_join(df, by = "id") %>% # 整理列顺序 select(id, fav_apple, fav_orange, fav_banana, fav_fruit) %>% # 转为因子变量 mutate(fav_fruit = as.factor(fav_fruit))
方法2:Base R 极简实现(无需转置)
直接对每行操作,效率更高,完全避免转置带来的重复问题:
# 提取所有水果列的名称 fruit_cols <- grep("fav_", names(df), value = TRUE) # 生成目标变量 df$fav_fruit <- apply(df[fruit_cols], 1, function(row) { # 找出当前行选中的水果列 selected_fruits <- names(row)[!is.na(row)] # 仅选一种则返回水果名,否则返回NA if (length(selected_fruits) == 1) { sub("fav_", "", selected_fruits) } else { NA_character_ } }) # 转为因子类型 df$fav_fruit <- as.factor(df$fav_fruit)
为什么你的pivot_longer方法会出现重复行?
当你用pivot_longer转长格式时,每个选中的水果都会生成一行记录——比如某受访者同时选了苹果和橙子,就会产生两行相同ID的记录。如果直接转置回宽格式,这些重复行无法自动合并,就会导致数据行数异常。解决的核心是先按ID分组,判断该受访者选中的水果数量是否为1,再提取对应值,而不是直接转置。
内容的提问来源于stack exchange,提问作者spindoctor
相关产品推荐
相关产品推荐

