R 函数中的 dplyr::summarise() 失败并出现 "argument not numeric or logical" 错误
dplyr::summarise() in an R function fails with "argument not numeric or logical" error
我对 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))
}
感觉自己好接近,结果报错:Warning message:In mean.default(pollutant, na.rm = TRUE) : argument is not numeric or logical:返回 NA。我认为错误是由于列 class 为 col_double。这可能是因为 dirdata 是从多个 csv 文件创建的。任何帮助将不胜感激。谢谢!
这是数据:zipfile_data
原始post中的代码失败,因为它在一个函数中使用了dplyr
,但没有使用dplyr
quoting functions。当我们通过 RStudio 调试器 运行 代码并停在第 7 行时,我们看到以下内容:
dplyr
没有按预期呈现 mean(pollutant, na.rm = TRUE)
中的函数参数,因此第 9 行失败。 mean()
函数失败,因为 pollutant
参数呈现为文本字符串,而不是 polspecdata
数据框中的列。
修复错误的一种方法是调整第 9 行以显式引用通过 %>%
管道运算符从先前函数传递的数据帧,使用提取运算符的 [[
形式使用参数的字符串版本。
polspecdatamean <- polspecdata %>% summarize(mean_pollutant=mean(.data[[pollutant]],na.rm=TRUE))
最后,由于函数应该 return 父环境的平均值,我们在函数末尾添加第 9 行中创建的对象的打印。
polspecdatamean
由于这是 Coursera 上约翰霍普金斯大学 R 编程 课程的编程作业,我不会 post 一个完整的答案,因为这违反了 Coursera 的荣誉代码.
简化解决方案
在第 5 行过滤数据后,函数可以简单地 return 平均值如下。
mean(specdata[[pollutant]],na.rm=TRUE)
结论
对于这个特定的作业,使用 dplyr
会使作业比需要的更难,因为 dplyr
使用非标准评估而 dplyr
不是'直到序列中的第三门课程,它甚至都包含在 JHU 课程中。
该代码还有其他一些细微的缺陷,我们将对其进行更正作为 reader 的练习。例如,给定分配要求,函数应该能够处理以下输入:
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
假设您将 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
评估为列而不是字符串。
我对 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))
}
感觉自己好接近,结果报错:Warning message:In mean.default(pollutant, na.rm = TRUE) : argument is not numeric or logical:返回 NA。我认为错误是由于列 class 为 col_double。这可能是因为 dirdata 是从多个 csv 文件创建的。任何帮助将不胜感激。谢谢!
这是数据:zipfile_data
原始post中的代码失败,因为它在一个函数中使用了dplyr
,但没有使用dplyr
quoting functions。当我们通过 RStudio 调试器 运行 代码并停在第 7 行时,我们看到以下内容:
dplyr
没有按预期呈现 mean(pollutant, na.rm = TRUE)
中的函数参数,因此第 9 行失败。 mean()
函数失败,因为 pollutant
参数呈现为文本字符串,而不是 polspecdata
数据框中的列。
修复错误的一种方法是调整第 9 行以显式引用通过 %>%
管道运算符从先前函数传递的数据帧,使用提取运算符的 [[
形式使用参数的字符串版本。
polspecdatamean <- polspecdata %>% summarize(mean_pollutant=mean(.data[[pollutant]],na.rm=TRUE))
最后,由于函数应该 return 父环境的平均值,我们在函数末尾添加第 9 行中创建的对象的打印。
polspecdatamean
由于这是 Coursera 上约翰霍普金斯大学 R 编程 课程的编程作业,我不会 post 一个完整的答案,因为这违反了 Coursera 的荣誉代码.
简化解决方案
在第 5 行过滤数据后,函数可以简单地 return 平均值如下。
mean(specdata[[pollutant]],na.rm=TRUE)
结论
对于这个特定的作业,使用 dplyr
会使作业比需要的更难,因为 dplyr
使用非标准评估而 dplyr
不是'直到序列中的第三门课程,它甚至都包含在 JHU 课程中。
该代码还有其他一些细微的缺陷,我们将对其进行更正作为 reader 的练习。例如,给定分配要求,函数应该能够处理以下输入:
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
假设您将 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
评估为列而不是字符串。