R语言统计DataFrame各列模式匹配占比的报错问题求解
R DataFrame模式匹配计数问题解决方案
原始测试数据
# 修正了原定义中缺失的逗号语法错误 df <- data.frame( "Foo"=c("a","c","NG-c","d","e","f"), "Bar"=c("b","b","c","d","e","f"), "Baz" = c("a","a","c","NG-c","NG-c","d"), "Gaz" = c("NG-c","NG-c","NG-c", "NG-a","NG-a","NG-a") ) pattern <- c("a","c")
需求说明
对DataFrame的每一列按指定模式完成查找、计数、对比操作,查找所有匹配NG-c的内容,输出每一列中NG-c的数量占对应模式总匹配数的百分比最高的列名,预期输出Baz和Gaz两个列名。
原代码问题排查
报错原因
- 循环索引写法错误:
for (i in ncol(df))只会遍历列数这单个数值,不会遍历所有列,正确写法应为for (i in 1:ncol(df)),内层循环for (pt in length(patern))存在同样问题。 - 边界值未处理:当列中没有匹配到目标模式时,总匹配数
tot为0,计算ng/tot会得到NaN,导致if判断缺少布尔值触发报错。 - 判断逻辑位置错误:
if (bg[pt] >= res)写在内层循环外,此时pt已经是循环的最后一个值,逻辑完全不符合预期。
警告原因
df[i]取到的是DataFrame的子数据框对象,不是原子向量,str_count要求传入字符串向量参数,因此触发类型强制转换的警告。
优化实现方案
采用向量化操作代替嵌套循环,代码更简洁且避免索引错误:
library(stringr) # 定义单列占比计算函数 calc_ngc_ratio <- function(col_vec, target = "c") { # 统计目标模式总匹配数(包含普通值和NG值) total_match <- sum(str_detect(col_vec, target)) # 统计NG开头的目标模式匹配数 ng_match <- sum(str_detect(col_vec, paste0("NG-", target))) # 处理总匹配数为0的边界情况 return(ifelse(total_match == 0, 0, ng_match / total_match * 100)) } # 批量计算所有列的NG-c占比 col_ratio <- sapply(df, calc_ngc_ratio) # 筛选占比最高的列名 names(col_ratio[col_ratio == max(col_ratio)])
运行后输出结果为:
[1] "Baz" "Gaz"
完全符合预期。
内容的提问来源于stack exchange,提问作者TeoK
相关产品推荐
相关产品推荐

