You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:32:50