如何结合使用ifelse与all函数实现分组赋值?
问题描述
需要按ID分组后给每组标记对应类型:
- 仅包含产品'A'的分组标记为'A'
- 仅包含产品'P'的分组标记为'P'
- 同时包含'A'和'P'的分组标记为'A_P'
- 不含'A'、'P'(全为NA)的分组标记为NA
使用的数据df:
df <- read.table(text = " ID Product 1 1 A 2 1 A 3 1 A 4 2 NA 5 2 NA 6 3 P 7 3 P 8 4 A 9 4 P 10 5 A 11 6 P 12 7 NA ")
期望输出:
ID Product Group 1 1 A A 2 1 A A 3 1 A A 4 2 NA NA 5 2 NA NA 6 3 P P 7 3 P P 8 4 A A_P 9 4 P A_P 10 5 A A 11 6 P P 12 7 NA NA
尝试的代码存在语法错误,无法生成目标列,同时有疑问:能否在ifelse语句中对非数值型向量使用all函数?
正确实现代码
使用dplyr分组结合case_when(逻辑更清晰)生成Group列,注意NA的判断必须用is.na,且要正确引用分组内变量:
library(dplyr) df <- df %>% group_by(ID) %>% mutate( Group = case_when( all(Product == "A", na.rm = TRUE) & !any(Product == "P", na.rm = TRUE) ~ "A", all(Product == "P", na.rm = TRUE) & !any(Product == "A", na.rm = TRUE) ~ "P", any(Product == "A", na.rm = TRUE) & any(Product == "P", na.rm = TRUE) ~ "A_P", all(is.na(Product)) ~ NA_character_ ) ) %>% ungroup()
如果想用ifelse嵌套实现,代码如下:
df <- df %>% group_by(ID) %>% mutate( Group = ifelse(all(Product == "A", na.rm = TRUE) & !any(Product == "P", na.rm = TRUE), "A", ifelse(all(Product == "P", na.rm = TRUE) & !any(Product == "A", na.rm = TRUE), "P", ifelse(any(Product == "A", na.rm = TRUE) & any(Product == "P", na.rm = TRUE), "A_P", ifelse(all(is.na(Product)), NA_character_, NA_character_))))) %>% ungroup()
错误原因解析
- 语法错误:你的
if/ifelse语句缺少闭合括号(比如if(all(df$Product=="A")末尾缺少)),且在dplyr分组操作中不能用df$Product引用整列,应直接用Product指向分组内的变量。 - NA判断错误:判断元素是否为NA不能用
Product == NA,必须用is.na(Product)——因为NA和任何值比较的结果都是NA,无法得到正确的逻辑判断。 - 逻辑漏洞:原代码未考虑分组同时存在A和P的场景,且
all(df$Product==NA)的写法完全错误。
疑问解答
可以在ifelse语句中对非数值型向量使用all函数。all函数的作用是判断向量中所有元素是否满足指定逻辑条件,和向量类型无关——比如all(Product == "A")就是对字符型向量的每个元素判断是否等于"A",最终返回是否所有元素都符合条件的逻辑值。
内容的提问来源于stack exchange,提问作者Jobolo
相关产品推荐
相关产品推荐

