如何在R自定义函数的group_by与summarise前删除NA值?
在自定义频率统计函数中正确剔除NA值
模拟数据
df = structure(list(country = c("USA", "USA", "Japan", NA), dimension = c("economic", "cultural", "economic", "economic"), score = c(NA, "high", "high", "low")), class = "data.frame", row.names = c(NA, -4L))
背景与问题
原本的export函数可以遍历数据框的每个变量,统计各值的频率并导出为以变量名命名的CSV文件:
export <- function(df){ for (col in colnames(df)) { table <- df %>% group_by(df[col]) %>% summarise(Count = n()) %>% mutate(Percent = Count / sum(Count)*100, N = sum(Count)) write.csv(table, paste0(col, ".csv"), row.names = F) print(table) } } export(df) # 可正常运行
但尝试添加filter(!is.na(df[col]))剔除NA值后,函数运行报错:
export <- function(df){ for (col in colnames(df)) { table <- df %>% filter(!is.na(df[col])) %>% # 尝试过滤NA值 group_by(df[col]) %>% summarise(Count = n()) %>% mutate(Percent = Count / sum(Count)*100, N = sum(Count)) write.csv(table, paste0(col, ".csv"), row.names = F) print(table) } } export(df) # 运行报错
错误信息如下:
Error in
group_by():
ℹ In argument:df[col].
Caused by error:
!df[col]must be size 3 or 1, not 4.
当前country变量的输出包含NA值(不符合需求):
country Count Percent N Japan 1 25 4 USA 2 50 4 NA 1 25 4
期望的country变量输出(剔除NA,不将其纳入频率统计):
country Count Percent N Japan 1 33.33333 3 USA 2 66.66667 3
问题根源
报错的核心是:filter(!is.na(df[col]))会将数据框的行数减少(比如country列过滤后只剩3行),但group_by(df[col])引用的是原始数据框的列(行数仍为4),导致维度不匹配。此外,用df[col]分组会生成以df[col]为列名的结果,可读性差。
修正后的函数
使用tidy求值的{{col}}语法来引用循环中的列名,确保过滤和分组操作的都是当前处理的列,且维度一致:
library(dplyr) export <- function(df){ for (col in colnames(df)) { table <- df %>% filter(!is.na({{col}})) %>% # 正确过滤当前列的NA值 group_by({{col}}) %>% # 正确按当前列分组 summarise(Count = n()) %>% mutate(Percent = Count / sum(Count)*100, N = sum(Count)) %>% rename(!!col := {{col}}) # 将分组列名改回原变量名,提升可读性 write.csv(table, paste0(col, ".csv"), row.names = F) print(table) } } export(df)
运行结果
修正后的函数运行后,country变量的输出完全符合期望:
# A tibble: 2 × 4 country Count Percent N <chr> <int> <dbl> <int> 1 Japan 1 33.3 3 2 USA 2 66.7 3
其他变量也会自动剔除对应列的NA值,生成正确的频率统计结果并导出为CSV文件。
内容的提问来源于stack exchange,提问作者johnjohn
相关产品推荐
相关产品推荐

