如何在ddply函数中使用字符串列名实现类Excel COUNTIF功能?
咱们来拆解下你的问题,先说说为什么result2和result3会出错:
result2里的df[,y]引用的是整个原始数据框的列,不是ddply拆分后的分组子数据框,所以每次计算的都是总行数5,自然得不到正确的分组计数。result3里的parse(text=x)只是生成了一个表达式对象,length()返回的是这个表达式的长度(永远是1),和分组数据完全没关系。
要实现用字符串列名完成类似COUNTIF的分组计数,核心是在ddply的summarise里,正确引用当前分组子数据框中的目标列。这里有几种可行的解决方案:
方法1:用get()函数提取分组内的列
get()可以根据字符串名称在当前环境中提取变量,而ddply的summarise运行时,当前环境就是每个分组的子数据框,所以这样写就能得到分组内的行数:
countif <- function(df, x ) { result2 <- ddply(df, x, summarise, countif = length(get(x))) return(result2) }
调用后会得到正确结果:
mycolumn countif 1 a 2 2 b 1 3 c 2
方法2:用.data代词引用列
plyr支持.data指代当前分组的子数据框,用列表索引的方式提取列会更清晰,也符合tidyverse的风格:
countif <- function(df, x ) { result2 <- ddply(df, x, summarise, countif = length(.data[[x]])) return(result2) }
额外推荐:用dplyr实现更现代的分组统计
如果你愿意尝试更主流的工具,dplyr的语法会更直观,处理字符串列名也更灵活:
library(dplyr) countif_dplyr <- function(df, x) { df %>% group_by(!!sym(x)) %>% # 将字符串列名转换为符号并分组 summarise(countif = n()) %>% # n()直接返回分组行数 ungroup() }
这个函数同样能得到正确的分组计数,代码可读性也更高。
最后补充一句:其实你的result1用nrow是完全正确的——ddply每个分组就是一个子数据框,nrow就是该分组的行数,和COUNTIF的核心功能完全匹配。如果只是需要基础的分组计数,result1已经满足需求;但如果要基于列做更复杂的条件统计,上面的方法就能帮你用字符串列名实现自定义逻辑。
内容的提问来源于stack exchange,提问作者gaut
相关产品推荐
相关产品推荐

