通过多个函数层使用点 (“...”) 参数时出现问题

Problem with using the dots ("...") argument through multiple function layers

提问人:mydeliciouspie 提问时间:3/28/2023 最后编辑:mydeliciouspie 更新时间:3/28/2023 访问量:45

问:

我正在尝试将 R-functions 的 dots-argument 用于数据导入函数。该函数应获取文件路径列表,并接受进一步的参数以传递给内部使用的函数。它应该导入指定的文件并将它们绑定到一个 DataFrame 中。输出将保存到全局环境中。data_listfread()

到目前为止的例子和想法:

我有一个文件夹“test1”,包含一个文件和一个文件夹“test2”,包含多个文件。这些文件是具有相同内部结构的 .txt 文件(在本例中为 4 行无用标头和 4 行数据),如下所示:

this is
a header
with some text
that should be ignored when importing
1;2;3;4
2;2;4;2
3;4;3;2
4;2;3;1

我生成我的列表:

data_list_1 <- list.files(path = "./test1", 
                          recursive = TRUE, 
                          pattern = "*.txt", 
                          full.names = TRUE)

data_list_2 <- list.files(path = "./test2", 
                          recursive = TRUE, 
                          pattern = "*.txt", 
                          full.names = TRUE)

在单个文件案例中,将参数传递给 works:fread()

data_import_test_1 <- function(data_list, ...) {
  .GlobalEnv$test_import <- fread(file = data_list, ...)
}

# imagine i have a fileset where i need to skip the first 4 rows when
# importing (data_list_1 contains a single file path)

data_import_test_1(data_list = data_list_1, skip = 4)

# output created is a dataframe of the specified file 
# without the first 4 rows

但是现在我想一次导入多个文件并将它们附加在一起,所以我想像这样包装它:fread()rbind()lapply()

data_import_test_2 <- function(data_list, ...) {
  .GlobalEnv$test_import <- do.call(what = rbind,
                                    args = lapply(data_list,
                                                  function(x, ...) fread(x, ...)))
}

# imagine i have multiple files of the same format as the single file 
# from the import above and data_list_2 contains all of them

data_import_test_2(data_list = data_list_2, skip = 4)

# output created still contains the rows i wanted to skip, 
# the skip = 4 argument doesnt reach fread()

有没有人知道如何处理移交,而不必将其硬编码到函数参数中?我将对来自不同来源的分割数据集使用我的函数,这些数据集需要不同的输入。这意味着我真的很想让我的函数动态地交出我需要的任何东西。

非常感谢大家看到这个,提前谢谢你!

我知道我可以像这样将参数硬编码到我的函数中:

data_import_test_2 <- function(data_list, fread_skip) {
  .GlobalEnv$test_import <- do.call(what = rbind,
                                    args = lapply(data_list,
                                                  function(x, fread_skip = fread_skip) 
                                                      fread(x, skip = fread_skip)))
}

我将希望对不同的数据集使用其他参数,并且我不想将它们全部包含在我的函数参数中,因为这会导致很多混乱和可读性降低。fread

r 函数 导入 参数传递

评论

1赞 Chris Cox 3/28/2023
我认为除了在函数定义中指定之外,您还需要将 作为参数传递给 。这是使用父函数中的变量和指定接受点的子函数之间的区别。...lapply......
1赞 Jan van der Laan 3/28/2023
我认为这应该行得通;甚至更短.lapply(data_list, function(x, ...) fread(x, ...), ...)lapply(data_list, fread, ...)
3赞 Jan van der Laan 3/28/2023
请不要在全球环境中分配。这很少是一个好的解决方案。
0赞 mydeliciouspie 3/28/2023
谢谢大家,我会尝试一下!错过了在 lappy 中另一个 ...-connector 的可能性
0赞 mydeliciouspie 3/28/2023
@JanvanderLaan 你更愿意用什么?我对 R 还很陌生,总是感谢提示和技巧!

答:

1赞 Chris Cox 3/28/2023 #1

您需要使用 from 父函数传递到子函数中...lapply(x, function(.x, ...) {do_something(.x, ...)}, ...)

例如,这将起作用:

sum_list_elements <- function(x, ...) {
    lapply(x, function(.x, ...) {
        sum(.x, ...)
    }, ...)
}
sum_list_elements(list(c(1,2,3,NA), c(4,5,6,NA)))
sum_list_elements(list(c(1,2,3,NA), c(4,5,6,NA)), na.rm = TRUE)

这不会:

sum_list_elements_broken <- function(x, ...) {
    lapply(x, function(.x, ...) {
        sum(.x, ...)
    })
}
sum_list_elements_broken(list(c(1,2,3,NA), c(4,5,6,NA)))
sum_list_elements_broken(list(c(1,2,3,NA), c(4,5,6,NA)), na.rm = TRUE)

评论

0赞 mydeliciouspie 3/28/2023
所以就我而言,我必须使用“......”我的 do.call() 和 lapply() 中的参数?现在就试试吧!谢谢你帮助我!编辑:do.call() 不需要也不想要我的“......”参数,但将其插入 lapply() 后,一切正常。
0赞 Chris Cox 3/29/2023
没错,你把点传进去,而不是.将点传递给 是告诉 R 将参数传递到数据帧的末尾,这不是您想要的。 和其他类似的函数允许您将“常量”参数传递给每个调用。例如,将常数 4 添加到每个数字 1:10(这不是有效的方法,只是演示一个概念)。lapplydo.calldo.callrbind...lapplylapply(1:10, `+`, 4)