簡體   English   中英

使用 apply 或 map 將列名稱傳遞到 function

[英]Pass column names into a function using apply or map

我想對同一個 dataframe 應用多個函數。但是,我無法成功地將列名作為參數傳遞給purrr::imap 我不斷收到以下錯誤:

UseMethod(“select”)中的錯誤:“select”沒有適用的方法應用於 class“字符”的 object

我已經嘗試了很多組合來進行評估(例如,使用!!![[enquosys.lang )。 當我將 function(例如check_1 )直接應用於 dataframe 時, select工作正常。 但是,當我嘗試使用imapexec將列名作為參數傳遞時,它不起作用。列名的格式是問題的一部分(例如1.1. ),但我嘗試了引號和單引號等。

這是上一篇文章的后續,但該文章和解決方案側重於將多個函數應用於各個列。 現在,我需要應用多個函數,其中使用了 dataframe 中的多個列; 因此,需要在 function 中指定列名。

最小的例子

數據

df <- structure(
  list(
    `1.1.` = c("Andrew", "Max", "Sylvia", NA, "1",
               NA, NA, "Jason"),
    `1.2.` = c(1, 2, 2, NA, 4, 5, 3, NA),
    `1.2.1.` = c(
      "cool", "amazing", "wonderful", "okay",
      NA, NA, "chocolate", "fine"
    )
  ),
  class = "data.frame",
  row.names = c(NA, -8L)
)

我試過的

library(purrr)
library(dplyr)

check_1 <- function(x, col1, col2) {
  x %>%
    dplyr::select(col1, col2) %>%
    dplyr::mutate(row.index = row_number()) %>%
    dplyr::filter(col1 == "Jason" & is.na(col2) == TRUE) %>%
    dplyr::select(row.index) %>%
    unlist() %>%
    as.vector()
}

check_2 <- function(x, col1, col2) {
  index <- x %>%
    dplyr::select(col1, col2) %>%
    dplyr::mutate(row.index = row_number()) %>%
    dplyr::filter(col1 >= 3 & col1 <= 5 & is.na(col2) == TRUE) %>%
    dplyr::select(row.index) %>%
    unlist() %>%
    as.vector()
  return(index)
}

checks <-
  list("df" = list(fn = check_1, pars = list(col1 = "1.1.", col2 = "1.2.")),
       "df" = list(fn = check_2, pars = list(col1 = "1.2.", col2 = "1.2.1.")))

results <-
  purrr::imap(checks, ~ exec(.x$fn, x = .y,!!!.x$pars))

預計 Output

> results
$df
[1] 8

$df
[1] 5 6

除了“類字符”錯誤之外,當我嘗試單獨測試check_2 function 時,我還遇到了一個額外的錯誤,它沒有返回預期值。

[1] 1.2.      1.2.1.    row.index
<0 rows> (or 0-length row.names)

我看過許多其他類似的 SO 帖子(例如, 這個),但沒有一個能為我解決這個問題。

第一個問題是您傳遞了 dataframe 的名稱,而不是 dataframe 本身。 這就是為什么在嘗試從字符串中select時出現第一個錯誤的原因。 要解決此問題,請將 dataframe 添加到您循環訪問的列表中。

第二個問題是,當您將列名作為字符串傳遞時,您必須告訴dplyr這些字符引用數據中的列。 這可以通過例如使用.data代詞來實現。

最后,您可以簡單地使用dplyr::pull代替select + unlist + as.vector

library(purrr)
library(dplyr)

check_1 <- function(x, col1, col2) {
  x %>%
    dplyr::select(all_of(c(col1, col2))) %>%
    dplyr::mutate(row.index = row_number()) %>%
    dplyr::filter(.data[[col1]] == "Jason" & is.na(.data[[col2]]) == TRUE) %>%
    dplyr::pull(row.index)
}

check_2 <- function(x, col1, col2) {
  x %>%
    dplyr::select(all_of(c(col1, col2))) %>% 
    dplyr::mutate(row.index = row_number()) %>%
    dplyr::filter(.data[[col1]] >= 3 & .data[[col1]] <= 5 & is.na(.data[[col2]]) == TRUE) %>%
    dplyr::pull(row.index)
}

checks <-
  list(df = list(df = df, fn = check_1, pars = list(col1 = "1.1.", col2 = "1.2.")),
       df = list(df = df, fn = check_2, pars = list(col1 = "1.2.", col2 = "1.2.1.")))

purrr::map(checks, ~ exec(.x$fn, x = .x$df, !!!.x$pars))
#> $df
#> [1] 8
#> 
#> $df
#> [1] 5 6

使用 select({{col1}},{{col2}}) 這最有可能幫助你

暫無
暫無

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

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