R语言避免循环统计data.table每行全列值更大的行数的方法
R data.table 无循环统计多列均严格大于当前行的行数
需求说明
现有data.table对象,每行对应一个个体,包含v1、v2、v3三个变量,需要为每一行统计所有个体中三个变量取值均严格大于当前行的总数量,存入count列,要求不使用循环实现。
原循环版本运行结果参考:
v1 v2 v3 count 1: 1.0 1.0 1.0 1 2: 1.0 1.5 1.0 0 3: 0.9 0.5 0.8 3 4: 2.0 1.5 2.0 0
方案1:向量化矩阵运算(实现最简单,中小数据量速度极快)
核心逻辑是利用R的矩阵广播特性,一次性完成所有行的两两比较,无需显式循环:
library(data.table) # 构造测试数据 A = data.table( v1 = c(1, 1, 0.9, 2), v2 = c(1, 1.5, 0.5, 1.5), v3 = c(1, 1, 0.8, 2) ) # 核心计算:三个比较矩阵取与后按行求和 A[, count := rowSums( (outer(v1, v1, `<`)) & (outer(v2, v2, `<`)) & (outer(v3, v3, `<`)) )] # 查看结果 print(A)
方案2:data.table 非等值自连接(适合大数据量,内存占用更低)
利用data.table原生的非等值连接特性,避免生成n*n的大矩阵,适合行数上万的场景:
library(data.table) A = data.table( v1 = c(1, 1, 0.9, 2), v2 = c(1, 1.5, 0.5, 1.5), v3 = c(1, 1, 0.8, 2) ) # 加行号用于分组统计 A[, id := .I] # 非等值自连接后按行统计符合条件的数量 res <- A[A, on = .(v1 > v1, v2 > v2, v3 > v3), nomatch = 0][, .(count = .N), by = id][A, on = .(id)][, id := NULL] print(res)
两种方案运行结果均和原循环版本完全一致。
内容的提问来源于stack exchange,提问作者Enrico
相关产品推荐
相关产品推荐

