【问题标题】:dplyr::summarise() in an R function fails with "argument not numeric or logical" errorR 函数中的 dplyr::summarise() 因“参数不是数字或逻辑”错误而失败
【发布时间】:2020-08-06 02:45:06
【问题描述】:

我对 R 比较陌生,我正在尝试编写我的第一个多步函数。本质上,我想创建一个函数,该函数接受一个目录并在该目录中搜索以找到某个列(在本例中为污染物)。然后找到该列的平均值并删除 NA。这是我目前所拥有的:

pollutantmean <- function(directory , pollutant , min_id = 1, max_id = 332) {

setwd(directory)

dirdata <- list.files(path=getwd() , pattern='*.csv' , full.names = TRUE) %>% lapply(read_csv) %>% bind_rows

specdata <- dirdata %>% filter(between(ID,min_id,max_id))

polspecdata <- specdata %>% select(pollutant)

polspecdatamean <- polspecdata %>% summarize(mean_pollutant=mean(pollutant,na.rm=TRUE))
} 

我觉得我很接近,但结果是错误:警告消息:在mean.default(污染,na.rm = TRUE):参数不是数字或逻辑:返回NA。我相信错误是由于列类是 col_double。这可能是由于 dirdata 是从多个 csv 文件创建的。任何帮助将不胜感激。谢谢!

这是数据:zipfile_data

【问题讨论】:

  • 嗨,M Doster,欢迎来到 SO。你能举个例子pollutant的样子吗?
  • 这是目录中 csv 文件的示例: head(csv1) # A tibble: 6 x 4 Date 硫酸盐硝酸盐 ID 1 2003-01 -01 NA NA 1 2 2003-01-02 NA NA 1 3 2003-01-03 NA NA 1 4 2003-01-04 NA NA 1 5 2003-01-05 NA NA 1 6 2003-01-06 NA NA 1
  • 尝试将mean应用于数字或逻辑列,即mean(pollutant$sulfate,na.rm=TRUE)$nitrate
  • 错误 "invalid for atomic vectors" 可能来自 $ 运算符,这意味着您正在尝试从不是 @987654329 的东西中获取帧列@(你说的是“性格”吗?)。老实说,M Doster,无论什么课程都使用pollutant,而且这个结构已经循环了很多次(每年),如果你在 SO 上搜索[r] pollutant,你会发现很多其他的都有可行的解决方案。不要复制,始终为课堂做自己的工作,但已知的工作示例可能非常有用。
  • @r2evans - 超过 400 万人在 Coursera 上参加了约翰霍普金斯大学的 R 编程 课程,因此在 SO 上有数千个关于 pollutantmean() 的问题也就不足为奇了。也就是说,可能很少有人对dplyr 非标准评估有问题,因为dplyr 直到JHU 课程R Programming 之后的课程才引入。

标签: r function dataframe dplyr mean


【解决方案1】:

原帖中的代码失败了,因为它在函数中使用了dplyr,但没有使用dplyrquoting functions。当我们通过 RStudio 调试器运行代码并在第 7 行停止时,我们会看到以下内容:

dplyr 没有按预期呈现mean(pollutant, na.rm = TRUE) 中的函数参数,因此第 9 行失败。 mean() 函数失败,因为 pollutant 参数呈现为文本字符串,而不是 polspecdata 数据框中的列。

修复错误的一种方法是调整第 9 行以显式引用通过 %&gt;% 管道运算符从先前函数传递的数据帧,使用提取运算符的 [[ 形式来使用字符串版本的论据。

polspecdatamean <- polspecdata %>% summarize(mean_pollutant=mean(.data[[pollutant]],na.rm=TRUE))

最后,由于函数应该将平均值返回给父环境,我们在函数末尾添加了第 9 行创建的对象的打印。

polspecdatamean

由于这是 Coursera 上约翰霍普金斯大学 R 编程 课程的编程作业,因此我不会发布完整的答案,因为这违反了 Coursera 荣誉准则。

简化解决方案

在第 5 行过滤数据后,函数可以简单地返回平均值,如下所示。

mean(specdata[[pollutant]],na.rm=TRUE)

结论

对于这个特定的作业,使用 dplyr 会使作业变得比实际需要的难度更大,因为 dplyr 使用非标准评估,而 dplyr 甚至没有包含在 JHU 课程中,直到序列中的第三门课程。

该代码还有一些其他细微的缺陷,我们将把它们的更正留给读者作为练习。例如,给定分配要求,该函数应该能够处理以下输入:

pollutantmean("specdata","sulfate",23) # calc mean for sensor 23
pollutantmean("specdata","nitrate",70:72) # calc mean for sensors 70 - 72 
pollutantmean("specdata","sulfate",c(3,5,7,9)) # calc mean for sensors 3, 5, 7, and 9 

【讨论】:

  • 非常感谢!几天来,我在尝试编写此代码时感到沮丧。至于 dplyr,coursera 课程并不是我学习过的唯一 R 编码课程,并且一直在使用多个课程的笔记来寻找要使用的功能。我需要用 [[ 查看更多示例,以便我希望将来更好地使用它们。再次感谢!
  • @MDoster - 感谢您的反馈。关于提取运算符[[ 形式的信息在我的文章Forms of the Extract Operator 中。祝 R 编程 课程的其余部分好运!
  • 对运算符的解释比讲座好得多。感谢您提供该资源。
【解决方案2】:

假设您将 pollutant 变量作为字符串传递,请尝试使用以下函数。

library(tidyverse)

pollutantmean <- function(directory , pollutant , min_id = 1, max_id = 332) {

  dirdata <- list.files(path=directory, pattern='*.csv' , full.names = TRUE) %>% 
                  map_df(read_csv)
   dirdata %>% 
      filter(between(ID,min_id,max_id)) %>%
      summarise(mean_pollutant= mean(!!sym(pollutant),na.rm=TRUE))
} 

所以你可以称它为

pollutantmean('/path', 'sulfate', 1, 10)

使用!!sym 我们将sulfate 评估为列而不是字符串。

【讨论】:

    猜你喜欢
    • 2021-01-29
    • 2020-11-16
    • 1970-01-01
    • 1970-01-01
    • 2022-06-20
    • 1970-01-01
    • 1970-01-01
    • 2018-10-01
    • 1970-01-01
    相关资源
    最近更新 更多