r - 使用 purrr::map_df 转发函数中的参数

标签 r purrr readxl

我正在尝试创建一个函数,该函数使用 readxl::read_excel 读取 Excel 工作簿中的所有工作表,并将它们绑定(bind)到单个数据框中,并允许我传递其他数据read_excel 的参数。我可以很好地完成第一部分,但不能完成第二部分。

library(magrittr)

# example excel workbook with multiple sheets
path <- readxl::readxl_example("datasets.xlsx")

# function with simple forwarding
read_all <- function(path, ...) {

  path %>%
    readxl::excel_sheets() %>%
    rlang::set_names() %>%
    purrr::map_df(~ readxl::read_excel(path = path, sheet = .x, ...))

}

# errors with and without additional arguments
read_all(path)
read_all(path, skip = 5)

我应该返回一个文件,但我收到一个错误:

Error: Can't guess format of this cell reference: iris
In addition: Warning message: Cell reference follows neither the A1 nor R1C1 format. Example: iris NAs generated.

没有参数传递函数工作正常:

# Function works without passing extra params
read_all_0 <- function(path) {

  path %>%
    readxl::excel_sheets() %>%
    rlang::set_names() %>%
    purrr::map_df(~ readxl::read_excel(path = path, sheet = .x))

}

read_all_0(path)

参数传递在简单函数中工作正常,无需 purrr::map_df

read_test <- function(path, ...) {

  path %>% readxl::read_excel(...)
}
read_test(path, skip = 10)

最佳答案

一种可能的解决方案是创建一个仅接受一个参数的命名函数,并将其传递给 map ,以便唯一的参数是您要循环的向量/列表。

应用于您的问题的解决方案将如下所示:

# function with forwarding
read_all <- function(path, ...) {

  # function within function that sets the arguments path and ellipsis as given and only leaves sheet to be determined
  read_xl <- function(sheet) {
    readxl::read_excel(path = path, sheet, ...)
  }

  path %>%
    readxl::excel_sheets() %>%
    rlang::set_names() %>%
    purrr::map_df(read_xl)

}

# this allows you to pass along arguments in the ellipsis correctly
read_all(path)
read_all(path, col_names = FALSE)

这个问题似乎是由于 purrr::as_mapper 函数的环境处理不当引起的。为了避免这种情况,我建议在评论中使用匿名函数。显然,下面的方法也有效。

read_all <- function(path, ...) {

  path %>%
    readxl::excel_sheets() %>%
    rlang::set_names() %>%
    purrr::map_df(function(x) {
                      readxl::read_excel(path = path, sheet = x, ...)
                   })

}

要验证是否确实是 as_mapper 函数导致了问题,我们可以使用 as_mapper 重写上面的命名函数中的函数。无论省略号中是否有附加参数,这都会再次产生错误。

# function with forwarding
read_all <- function(path, ...) {

  # named mapper function
  read_xl <- purrr::as_mapper(~ readxl::read_excel(path = path, sheet = .x, ...))

  path %>%
    readxl::excel_sheets() %>%
    rlang::set_names() %>%
    purrr::map_df(read_xl)

} 

更新 知道 as_mapper 导致了这个问题,这让我们能够更深入地研究这个问题。现在,我们可以在 RStudio 调试器中检查运行简单映射器版本的 read_excel 时幕后发生的情况:

read_xl <- purrr::as_mapper(~ readxl::read_excel(path = .x, sheet = .y, ...))
debugonce(read_xl) 
read_xl(path, 1)

似乎当省略号包含在映射器函数中时,as_mapper 不仅将第一个参数映射到 .x,而且还自动映射到省略号 。 ..。我们可以通过创建一个带有两个参数 .x... 的简单映射器函数 paster 来验证这一点。

paster <- purrr::as_mapper(~ paste0(.x, ...))
paster(1)
> [1] "11"
paster(2)
> [1] "22"

现在的问题是:我们是否应该在映射器函数中使用省略号的另一种方式,或者这是一个错误。

关于r - 使用 purrr::map_df 转发函数中的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58243710/

相关文章:

css - Shiny 的 R - 允许滚动条在 div 之上而不是在 div 之内

r - 如何使用 purrr 匹配查找表中的记录?

r - map + pmap,找不到变量

r - 映射列并使用 map_dbl 提取第一个数字

r - 使用R读出excel-colorinfo

r - download.file() 下载损坏的 xls

r - 如何将 df 绑定(bind)到 df 列表

r - 如何过滤此数据框?

r - 使用 R 包 : readxl and writing to a csv 按列合并多个 .xlsx 文件时出现标题前有垃圾文本的问题

mysql - 在 R 中使用 RMySQL 和 .my.cnf 文件连接到数据库