基于多条件为data.table新增列的技术求助(ifelse方法失效)
在data.table中按多区间条件新增列的正确实现方法
嘿,我知道你碰到了data.table多条件赋值的坑——用ifelse的时候居然全变成"A"了对吧?别慌,这其实是因为普通的if...else是标量判断(只处理第一个元素),就算用ifelse如果嵌套顺序不对也会出问题。下面给你几个适配data.table的高效解决办法:
方法1:用data.table专属的fcase函数(首推)
fcase是data.table专门为向量化多条件判断设计的函数,语法清晰、运行高效,完全贴合data.table的操作逻辑:
library(data.table) # 初始化你的数据 a <- data.table(col1=c(7,85,1905,22,250)) # 新增col2列并赋值 a[, col2 := fcase( col1 < 10, "A", # 第一个条件:col1小于10时赋值"A" col1 < 100, "B", # 第二个条件:不满足上一个但小于100时赋值"B" col1 < 1000, "C", # 第三个条件:不满足前两个但小于1000时赋值"C" default = "D" # 其余情况赋值"D" )]
运行后就能得到你想要的结果:
col1 col2
1: 7 A
2: 85 B
3: 1905 D
4: 22 B
5: 250 C
方法2:正确嵌套基础R的ifelse函数
如果你习惯用基础R的ifelse,一定要注意条件的嵌套顺序——要从最严格的条件开始往下写(因为ifelse是向量化的,只要满足前面的条件就会返回对应值):
a[, col2 := ifelse(col1 < 10, "A", ifelse(col1 < 100, "B", ifelse(col1 < 1000, "C", "D")))]
之前你得到全"A"的结果,大概率是误用了普通的if(标量判断)而非向量化的ifelse,或者嵌套顺序搞反了。
方法3:用cut函数快速分区间映射
因为你的条件是连续的数值区间,用cut函数也能快速实现映射,代码更简洁:
a[, col2 := cut(col1, breaks = c(-Inf, 10, 100, 1000, Inf), # 划分区间 labels = c("A", "B", "C", "D"), # 对应区间的标签 include.lowest = TRUE)] # 让最小值区间包含边界值
这里include.lowest = TRUE确保等于10的数值会被分到下一个区间(也就是"B"),刚好匹配你col1 <10才赋值"A"的需求。
内容的提问来源于stack exchange,提问作者Yuva
相关产品推荐
相关产品推荐

