簡體   English   中英

R function 中的 dplyr::summarise() 因“參數不是數字或邏輯”錯誤而失敗

[英]dplyr::summarise() in an R function fails with “argument not numeric or logical” error

我對 R 比較陌生,我正在嘗試編寫我的第一個多步驟 function。 本質上,我想創建一個 function,它采用一個目錄並在該目錄中搜索以找到某個列(在本例中為污染物)。 然后找到該列的平均值並刪除 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。 我相信該錯誤是由於 class 列是 col_double 造成的。 這可能是由於 dirdata 是從多個 csv 文件創建的。 任何幫助將不勝感激。 謝謝!

這是數據: zipfile_data

原始帖子中的代碼失敗,因為它在dplyr中使用 dplyr,但不使用dplyr引用函數 當我們通過 RStudio 調試器運行代碼並在第 7 行停止時,我們看到以下內容:

在此處輸入圖像描述

dplyr預期在mean(pollutant, na.rm = TRUE)內呈現 function 參數,因此第 9 行失敗。 mean() function 失敗,因為pollutant參數呈現為文本字符串,而不是polspecdata數據框中的列。

修復錯誤的一種方法是調整第 9 行,以顯式引用從先前的 function 通過%>% pipe 運算符傳遞的數據幀,使用提取運算符的[[形式來使用參數的字符串版本。

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

最后,由於 function 應該將平均值返回給父環境,因此我們在 function 的末尾添加了在第 9 行創建的 object 的打印。

polspecdatamean

由於這是針對 Coursera 上的約翰霍普金斯大學R 編程課程的編程作業,因此我不會發布完整的答案,因為這違反了 Coursera 榮譽准則。

簡化解決方案

在第 5 行過濾數據后,function 可以簡單地返回平均值,如下所示。

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

結論

對於這個特定的作業,由於dplyr使用非標准評估和dplyr甚至在 JHU 課程的第三個課程序列中都沒有涵蓋,因此使用dplyr使作業比所需的難度更大。

該代碼還有其他一些細微的缺陷,我們將把它們的更正留給讀者作為練習。 例如,給定分配要求,function 應該能夠處理以下輸入:

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變量作為字符串傳遞,請嘗試使用以下 function。

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評估為列而不是字符串。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM