R数据框新增列问题:mutate结合any()未达预期结果
问题分析
你的代码问题出在mutate里的any(unlist(groupMap$allowed) == TRUE):unlist会把所有行的allowed列表元素展开成一个单一向量,any()对这个整体向量判断是否存在TRUE,结果是一个单个的逻辑值(这里因为确实有多个TRUE,所以返回TRUE),mutate会把这个值重复赋值给每一行,导致Allow列全为TRUE。
解决方法
下面提供几种简洁的修正方案:
方案1:修正原有代码,逐行判断列表中的TRUE
利用sapply或purrr::map_lgl对每行的allowed列表单独判断是否存在TRUE:
library(dplyr) library(stringr) GroupName <- c("Mayfair", "Chronos", "Orion", "Milkhouse", "Saddle", "Westeros") Region <- c("A12", "S19", "T12", "T11", "S16", "B2") GroupAssociation <- data.frame(GroupName, Region) regID <- c("S", "T1") groupMap <- GroupAssociation groupMap$allowed <- lapply(groupMap$Region, stringr::str_starts, regID) # 用sapply逐行判断 groupMap$Allow <- sapply(groupMap$allowed, any) # 或者用dplyr+purrr的写法 # groupMap <- groupMap %>% mutate(Allow = purrr::map_lgl(allowed, any))
方案2:一步到位,无需中间列表列
直接利用str_starts的向量化特性,结合rowSums判断每行是否有匹配:
library(dplyr) library(stringr) GroupName <- c("Mayfair", "Chronos", "Orion", "Milkhouse", "Saddle", "Westeros") Region <- c("A12", "S19", "T12", "T11", "S16", "B2") GroupAssociation <- data.frame(GroupName, Region) regID <- c("S", "T1") groupMap <- GroupAssociation %>% mutate(Allow = rowSums(str_starts(Region, regID)) > 0)
原理:str_starts(Region, regID)会返回一个n行2列的矩阵(n是数据行数),每行对应一个Region与两个regID的匹配结果;rowSums计算每行的TRUE数量(TRUE被视为1,FALSE为0),大于0就说明该行存在至少一个匹配。
方案3:用rowwise逐行处理
如果习惯dplyr的管道风格,也可以用rowwise逐行判断:
groupMap <- GroupAssociation %>% rowwise() %>% mutate(Allow = any(str_starts(Region, regID))) %>% ungroup()
rowwise()会让后续的mutate逐行执行,any()只对当前行的匹配结果判断。
内容的提问来源于stack exchange,提问作者Mikey
相关产品推荐
相关产品推荐

