如何简洁实现R语言中行级多列数值全部相等的检查
嘿,我完全懂你觉得原来的gather/spread方法太繁琐的感受!其实有好几种更简洁的方式来实现行级检查指定多列数值是否全部相等的需求,不管你偏好base R、dplyr还是data.table都能搞定,下面给你一一演示:
先确认示例数据
首先咱们先把示例数据生成好(和你原来的一致,只是写法更简洁):
set.seed(4) sample_df <- data.frame( id = letters[1:6], group = rep(c('r','l'),3), V3 = sample(1:4, 6, replace = TRUE), V4 = sample(1:4, 6, replace = TRUE), V5 = sample(1:4, 6, replace = TRUE), stringsAsFactors = FALSE )
方法1:Base R 极简实现
不需要任何额外包,用apply就能快速搞定:
# 方式A:检查每行所有值是否等于该行第一列的值 sample_df$test <- apply(sample_df[, 3:5], 1, function(x) all(x == x[1])) # 方式B:计算每行的唯一值数量是否为1 sample_df$test <- apply(sample_df[, 3:5], 1, function(x) length(unique(x)) == 1)
这两种方式都能直接得到你想要的test列,结果和你期望的完全一致。
方法2:dplyr 简洁写法(推荐)
如果你习惯用tidyverse,dplyr的rowwise或者across(1.0.0+版本支持)能让代码更易读:
library(dplyr) # 方式A:rowwise + n_distinct sample_df %>% rowwise() %>% mutate(test = n_distinct(c(V3, V4, V5)) == 1) %>% ungroup() # 方式B:用across实现更通用的列范围检查(不用硬编码列数) sample_df %>% mutate( test = across(V3:V5, ~ .x == pick(V3)) %>% rowSums() == ncol(pick(V3:V5)) )
across的写法特别适合当你要检查的列范围变化时,不用修改代码里的数字,灵活性拉满。
方法3:data.table 高效处理(适合大数据集)
如果你的数据量很大,data.table的行级操作会更高效:
library(data.table) setDT(sample_df) sample_df[, test := uniqueN(.SD) == 1, .SDcols = V3:V5]
这里uniqueN(.SD)会计算每行指定列的唯一值数量,判断是否等于1即可。
所有这些方法最终得到的test列都和你期望的输出一致:第5行(id=e)为TRUE,其余为FALSE,而且代码比原来的gather/spread流程简洁太多啦!
内容的提问来源于stack exchange,提问作者tjebo
相关产品推荐
相关产品推荐

