我对R比较陌生,我正在尝试编写我的第一个多步骤函数。本质上,我想创建一个函数,接受一个目录,并在该目录中搜索,以找到某个列(在本例中,污染物)。然后找到该列的平均值,并去除NAs。这就是我目前的成果。
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: returning NA. 我相信这个错误是由于列类是col_double。这可能是由于dirdata是由多个csv文件创建的。任何帮助都将是非常感激的。谢谢你的帮助
这是数据。zipfile_data
原帖中的代码失败了,因为它使用了 dplyr
的函数中,但不使用 dplyr
引用功能. 当我们通过 RStudio 调试器运行代码并在第 7 行停止时,我们看到以下内容。
dplyr
没有将函数参数呈现在 mean(pollutant, na.rm = TRUE)
正如预期的那样,所以第9行失败。该 mean()
函数失败,因为 pollutant
参数以文本字符串的形式呈现,而不是以列的形式出现在 polspecdata
数据帧。
修正错误的方法之一是调整第9行,通过以下方法显式引用前一个函数传递过来的数据帧 %>%
管道运营商,使用 [[
的形式来使用参数的字符串版本。
polspecdatamean <- polspecdata %>% summarize(mean_pollutant=mean(.data[[pollutant]],na.rm=TRUE))
最后,由于函数应该将平均数返回到父环境,所以我们在函数的最后添加一个第9行创建的对象的打印。
polspecdatamean
由于这是约翰-霍普金斯大学的编程作业。R编程 Coursera上的课程,我不会发布完整的答案,因为这违反了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
假设你传递的是 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
作为列而不是字符串。