在R中使用Apply或MAP函数时,如何将列名传递给函数? [英] How to pass column names into a function when using an apply or map function in R?

查看:10
本文介绍了在R中使用Apply或MAP函数时,如何将列名传递给函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将多个函数应用于同一个DataFrame,但我无法成功地将列名作为参数传递,该参数使用purrr::imap。但是,我一直收到以下错误:

UseMethod(&QOOT;SELECT&QOOT;)中出错:没有适用于‘SELECT’的方法 应用于类&Character&Quot;的对象

我尝试了在SO上找到的所有组合(例如,使用!!![[enquosys.lang等等)。当我将函数(例如,check_1)直接应用于数据帧时,我可以使select工作,但在使用imapexec时尝试将列名作为参数传递时,我无法使select工作。列名的格式是问题的一部分(例如,1.1.),但尝试了引号和单引号等。

这是previous post的后续,但该帖子和解决方案侧重于将多个函数应用于各个列。现在,我需要应用多个函数,这些函数使用数据帧中的多个列;因此,需要在函数中指定列名。我确信有可能将其整合到另一个框架中,但我想先自己试一试。

最小示例

数据

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))

预期输出

> results
$df
[1] 8

$df
[1] 5 6

除了";类字符错误外,当我尝试单独测试check_2函数时,我还收到一个额外的错误,其中它不返回任何预期值。

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

我看过很多其他类似的so帖子(例如this one),但没有一个为我解决这个问题。

推荐答案

第一个问题是您传递的是数据帧的名称,而不是数据帧本身。这就是为什么当您尝试从字符串select时收到第一个错误的原因。若要解决此问题,请将数据帧添加到您正在循环的列表中。

第二个问题是,当您将列名作为字符串传递时,您必须告诉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

这篇关于在R中使用Apply或MAP函数时,如何将列名传递给函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆