使用dplyr匹配不同长度向量生成新变量y的问题
解决列表列匹配向量的case_when问题
我明白你遇到的问题了——当你的数据框里是列表列(每个单元格是一个独立向量)时,直接用case_when和普通向量做==比较,会因为向量长度不匹配触发警告,而且没法正确匹配到对应的向量标识。
问题根源
你的df$x是列表类型,每个元素是长度不同的字符向量。当你写x == vec1时,R会尝试把vec1循环拉长来匹配x中每个元素的长度,这就导致了"longer object length is not a multiple of shorter object length"的警告;同时这种比较方式没法判断整个列表元素是否和目标向量完全一致,所以case_when没有匹配到任何条件,最终得到空的y列。
解决方案
我们需要逐个检查列表列中的每个向量,判断它和vec1/vec2/vec3是否完全相等。这里提供两种实用的实现方式:
方法1:使用purrr::map_chr
借助purrr的遍历函数,逐个处理列表列的每个元素:
library(dplyr) library(purrr) df <- tibble::tribble( ~x, c("A", "B"), c("A", "B", "C"), c("A", "B", "C", "D"), c("A", "B") ) vec1 <- c("A", "B") vec2 <- c("A", "B", "C") vec3 <- c("A", "B", "C", "D") df <- df %>% mutate(y = map_chr(x, ~ case_when( identical(.x, vec1) ~ "vec1", identical(.x, vec2) ~ "vec2", identical(.x, vec3) ~ "vec3", TRUE ~ NA_character_ ))) df
方法2:使用rowwise + case_when
如果更习惯dplyr的行操作逻辑,可以先按行分组再判断:
df <- df %>% rowwise() %>% mutate(y = case_when( identical(x, vec1) ~ "vec1", identical(x, vec2) ~ "vec2", identical(x, vec3) ~ "vec3", TRUE ~ NA_character_ )) %>% ungroup() df
两种方法都会得到正确的结果:
# A tibble: 4 × 2 x y <list> <chr> 1 <chr [2]> vec1 2 <chr [3]> vec2 3 <chr [4]> vec3 4 <chr [2]> vec1
关键说明
identical()函数用来判断两个向量是否完全一致(包括长度、元素顺序和类型),这是正确匹配的核心。map_chr()会遍历列表列的每个元素,把每个元素的判断结果整合成一个字符向量,正好适合作为新列y。
内容的提问来源于stack exchange,提问作者Geet
相关产品推荐
相关产品推荐

