R语言多层嵌套for循环与条件判断代码优化求助
R代码优化:替代嵌套for循环实现条件统计
原始数据与需求
数据定义
set.seed(10) df<-data.frame(val1 = c(1.1,0.2,-1.5,-2.3,2.0), val2 = c(0.4,0.1,-0.2,0.4,-1.1)) l <- list( data.frame(val1 = runif(5,-3,3), val2 = runif(5,-2,2)), data.frame(val1 = runif(5,-3,3), val2 = runif(5,-2,2)), data.frame(val1 = runif(5,-3,3), val2 = runif(5,-2,2)) )
统计需求
- 若
df中某元素为正,统计列表l中所有对应位置元素大于该元素的次数 - 若
df中某元素为负,统计列表l中所有对应位置元素小于该元素的次数
原始嵌套循环实现
mat = matrix(0, nrow=5, ncol = 2) for(i in 1:3){ for(c in 1:2){ for(r in 1:5){ if(df[r,c]>0){ if(l[[i]][r,c]>df[r,c]){ mat[r,c] = mat[r,c]+1 } } else if(l[[i]][r,c]<df[r,c]){ mat[r,c] = mat[r,c]+1 } } } }
期望输出:
mat [,1] [,2] [1,] 1 1 [2,] 2 1 [3,] 1 3 [4,] 0 2 [5,] 0 0
优化方案:向量化运算 + 列表合并
嵌套循环在R中存在明显性能瓶颈,尤其是数据规模较大时。通过向量化运算结合列表格式转换,可大幅提升代码运行效率,具体步骤如下:
步骤1:将列表转换为三维数组
把列表l中的所有数据框合并为一个三维数组,实现批量位置匹配:
arr <- simplify2array(l)
步骤2:生成条件判断矩阵
根据df元素的正负,生成对应位置的布尔判断矩阵:
# 正元素判断:arr对应位置大于df;负元素判断:arr对应位置小于df cond <- (df > 0 & arr > df) | (df <= 0 & arr < df)
步骤3:按位置求和得到结果
对三维数组的第三个维度(对应列表的每个元素)求和,直接得到每个位置的统计次数:
mat_opt <- apply(cond, c(1,2), sum)
完整优化代码
set.seed(10) df<-data.frame(val1 = c(1.1,0.2,-1.5,-2.3,2.0), val2 = c(0.4,0.1,-0.2,0.4,-1.1)) l <- list( data.frame(val1 = runif(5,-3,3), val2 = runif(5,-2,2)), data.frame(val1 = runif(5,-3,3), val2 = runif(5,-2,2)), data.frame(val1 = runif(5,-3,3), val2 = runif(5,-2,2)) ) # 优化实现 arr <- simplify2array(l) cond <- (df > 0 & arr > df) | (df <= 0 & arr < df) mat_opt <- apply(cond, c(1,2), sum) # 查看结果 mat_opt
运行输出与期望完全一致:
val1 val2 [1,] 1 1 [2,] 2 1 [3,] 1 3 [4,] 0 2 [5,] 0 0
效率说明
向量化运算规避了循环的性能损耗,当列表元素数量、数据框行列数增加时,速度提升会更显著。例如当列表包含100个元素、数据框为1000行×100列时,优化后的代码运行速度会比嵌套循环快数十倍。
内容的提问来源于stack exchange,提问作者jalapic
相关产品推荐
相关产品推荐

