R语言基于双条件无循环快速删除数据框指定行的方法
按双匹配条件高效筛选数据框行
需求说明
需要基于两个条件删除数据框行:
- 行名匹配预定义字符向量中的任意值
- 列名与另一个预定义字符向量存在部分匹配
当前采用嵌套for循环逐单元格判断赋值,原始数据行数超过20万,运行效率极低,需要无循环的高效替代方案。
原有循环实现代码
# 生成随机测试数据框 set.seed(seed = 100) df.data <- runif(80, 0,1) df <- as.data.frame(matrix(df.data, nrow = 10, ncol = 8, dimnames = list(rownames = seq(1,10), colnames = paste(c("A", "B"), rep(c("150","250"),4), sep = "_")))) # 预定义匹配向量 columns_to_filter <- c("150", "250") rows_to_filter <- sort(round(runif(10, min = 1, max = 10), digits = 0)) # 嵌套循环实现:匹配位置替换为NA后删除含NA行 for(ii in 1:ncol(df)){ for(jj in 1:nrow(df)){ if(length(which(str_detect(colnames(df)[ii], columns_to_filter)) == TRUE) > 0){ if(jj %in% rows_to_filter){ df[jj,ii] <- NA } } else{ df[jj,ii] <- df[jj,ii] } } } df <- na.omit(df) dim(df)
测试数据参考
原始df的dput输出
structure(list(A_150 = c(0.338048706296831, 0.905447596916929, 0.197556710103527, 0.794085179455578, 0.754602894652635, 0.911394847324118, 0.322687704581767, 0.0861694731283933, 0.911200454225764, 0.95517382514663 ), B_250 = c(0.671142943901941, 0.744982200907543, 0.440016976324841, 0.115039417985827, 0.675642782123759, 0.731559516629204, 0.483984902733937, 0.171048037940636, 0.675848534796387, 0.262989946408197), A_150 = c(0.34148082928732, 0.210245542926714, 0.0163195941131562, 0.376762877451256, 0.562307401793078, 0.679984607733786, 0.745388770475984, 0.950072722276673, 0.163090714253485, 0.324756902176887), B_250 = c(0.132716035470366, 0.637297438690439, 0.330929610645398, 0.649079572875053, 0.302888358943164, 0.0712332662660629, 0.662390468874946, 0.75960356160067, 0.553360169287771, 0.539272097637877 ), A_150 = c(0.849592320388183, 0.653225958812982, 0.950885756406933, 0.617223048349842, 0.49284063372761, 0.976006565382704, 0.490345216123387, 0.655172303086147, 0.598801789339632, 0.947569016367197), B_250 = c(0.368011507438496, 0.878187005175278, 0.454875067807734, 0.496467015240341, 0.460615615127608, 0.617908196756616, 0.604143491946161, 0.785879602655768, 0.555268474854529, 0.768978339154273), A_150 = c(0.404285672586411, 0.510719809681177, 0.523536442779005, 0.992799207800999, 0.429647421231493, 0.996011254843324, 0.786600246559829, 0.515910634538159, 0.502687965519726, 0.911637484328821 ), B_250 = c(0.264415897428989, 0.173856867710128, 0.400331255048513, 0.538357384037226, 0.244964374694973, 0.37585095805116, 0.58025354729034, 0.208955311682075, 0.801330007379875, 0.638802415458485)), class = "data.frame", row.names = c("1", "2", "3", "4", "5", "6", "7", "8", "9", "10"))
循环处理后df的dput输出
structure(list(A_150 = c(0.338048706296831, 0.905447596916929, 0.794085179455578, 0.911200454225764), B_250 = c(0.671142943901941, 0.744982200907543, 0.115039417985827, 0.675848534796387), A_150 = c(0.34148082928732, 0.210245542926714, 0.376762877451256, 0.163090714253485), B_250 = c(0.132716035470366, 0.637297438690439, 0.649079572875053, 0.553360169287771), A_150 = c(0.849592320388183, 0.653225958812982, 0.617223048349842, 0.598801789339632), B_250 = c(0.368011507438496, 0.878187005175278, 0.496467015240341, 0.555268474854529), A_150 = c(0.404285672586411, 0.510719809681177, 0.992799207800999, 0.502687965519726), B_250 = c(0.264415897428989, 0.173856867710128, 0.538357384037226, 0.801330007379875)), row.names = c("1", "2", "4", "9"), class = "data.frame", na.action = structure(c(`3` = 3L, `5` = 5L, `6` = 6L, `7` = 7L, `8` = 8L, `10` = 10L), class = "omit"))
高效向量化实现方案
嵌套循环逐单元格操作是R里最低效的写法,针对20万行规模的数据,直接用R原生向量化索引即可完成操作,全程不需要循环,运行速度比嵌套循环快数百倍,结果和原逻辑完全一致。
实现逻辑:
- 一次性批量匹配所有符合部分匹配规则的目标列,替代逐列判断
- 直接通过矩阵索引批量给目标行、目标列的交叉位置赋值NA,替代逐单元格赋值
- 最后统一删除包含NA的行
对应代码:
library(stringr) # 1. 批量匹配所有符合规则的列:列名包含columns_to_filter中任意字符串 match_pattern <- paste(columns_to_filter, collapse = "|") target_cols <- colnames(df)[str_detect(colnames(df), match_pattern)] # 2. 批量给目标行、目标列位置赋值NA target_rows <- rownames(df) %in% rows_to_filter df[target_rows, target_cols] <- NA # 3. 删除含NA的行 df_result <- na.omit(df)
内容的提问来源于stack exchange,提问作者Mansi
相关产品推荐
相关产品推荐

