【问题标题】:Reading function input values defined in `...` from an CSV file in R从 R 中的 CSV 文件中读取“...”中定义的函数输入值
【发布时间】:2019-11-05 03:29:21
【问题描述】:

假设我有一个 R 函数,例如下面的 foo。此函数有 4 个固定参数,以及在... 中定义的任意数量的任意参数。

foo 参数的所有输入值都存储在 THIS CSV 文件中。

在下面的代码中,我可以在 lapply 循环中使用从 CSV 文件导入的 4 个固定参数成功运行 foo但是我想知道如何在lapply 命令中插入... 中定义的参数?

foo <- function(n = NULL, r = NULL, post, control, ...){ ## the function

data.frame(n = n, r = r, post, control, ...)

}

D <- read.csv("https://raw.githubusercontent.com/izeh/i/master/j.csv", h = T) # CSV file
L <- split(D, D$study.name) ; L[[1]] <- NULL

# the fixed args values:
      n <- lapply(1:length(L), function(i) L[[i]]$n)
      r <- lapply(1:length(L), function(i) L[[i]]$r)
   post <- lapply(1:length(L), function(i) L[[i]]$post)
control <- lapply(1:length(L), function(i) L[[i]]$control)

# names of args defined in `...`:
dot.names <- names(L[[1]])[!names(L[[1]]) %in% formalArgs(foo)][-1]

# the `...` args values:
a <- lapply(dot.names, function(i) lapply(L, function(j) j[grep(i, names(j))]))

## RUN `foo` function:
lapply(1:length(L), function(i) foo(n = n[[i]], r = r[[i]], post = post[[i]], 
                                     control = control[[i]])) # BUT! how can I insert the 
                                                              # arguments defined in `...` 
                                                              # in the function?

【问题讨论】:

  • 如果您使用了这么多lapply 调用,可能是时候编写一个函数了。 dots 在函数中更容易使用。
  • 从之前的帖子,不得不稍作改动。请检查base R的更新

标签: r function loops dataframe lapply


【解决方案1】:

使用mapply 解决此类问题。
在下面的代码中,我更改了您定义nrpostcontrol 的方式。

n <- lapply(L, `[[`, 'n')
r <- lapply(L, `[[`, 'r')
post <- lapply(L, `[[`, 'post')
control <- lapply(L, `[[`, 'control')

唯一的区别是这些结果具有names 属性集。

然后还要更改列表列表a 的创建方式。交换两个循环。

a <- lapply(L, function(i) lapply(dot.names, function(k) i[grep(k, names(i))]))

现在解决问题。必须设置SIMPLIFY = FALSE,默认TRUE 输出非常糟糕。

mapply(FUN = foo, n, r, post, control, a, SIMPLIFY = FALSE)

【讨论】:

    【解决方案2】:

    我们还可以将Mapdo.call 一起使用。我们可以在对lapply 的一次调用中提取foo 的参数,方法是根据'的输出提取列'n'、'r'、'post'、control'和额外的列(...) dot.names',然后transpose(来自purrr - 或使用与here相同的方法)并将其传递给Map

    args <- lapply(L, function(x) unclass(x[c("n", "r", "post", "control", dot.names)]))
    library(purrr)
    unname(do.call(Map, c(f = foo, transpose(args))))
    #[[1]]
    #   n   r post control ESL prof scope type
    #1 13 0.5    1   FALSE   1    2     0    1
    #2 13 0.5    2   FALSE   1    2     0    1
    #3 15 0.5    1   FALSE   1    2     0    1
    #4 15 0.5    2   FALSE   1    2     0    1
    #5 16 0.5    1    TRUE   1    2     0    1
    #6 16 0.5    2    TRUE   1    2     0    1
    
    #[[2]]
    #   n   r post control ESL prof scope type
    #1 13 0.5    1   FALSE   0    1     1    0
    #2 13 0.5    2   FALSE   0    1     1    0
    #3 15 0.5    1   FALSE   0    1     1    0
    #4 15 0.5    2   FALSE   0    1     1    0
    #5 16 0.5    1    TRUE   0    1     1    0
    #6 16 0.5    2    TRUE   0    1     1    0
    
    #[[3]]
    #   n   r post control ESL prof scope type
    #1 13 0.5    1   FALSE   1    3     0    1
    #2 13 0.5    2   FALSE   1    3     0    1
    #3 13 0.5    3   FALSE   1    3     0    1
    #4 15 0.5    1   FALSE   1    3     0    1
    #5 15 0.5    2   FALSE   1    3     0    1
    #6 15 0.5    3   FALSE   1    3     0    1
    #7 16 0.5    1    TRUE   1    3     0    1
    #8 16 0.5    2    TRUE   1    3     0    1
    #9 16 0.5    3    TRUE   1    3     0    1
    

    OP 提到用 base R 选项替换 transpose

    m1 <- simplify2array(lapply(names(args[[1]]), function(nm) 
         lapply(args, function(l1) l1[nm])))
    do.call(Map, c(f = foo, unname(split(m1, col(m1)))))
    

    如果我们可以使用tidyverse

    library(tidyverse)
    map(L, ~ 
           .x %>%
               select(n, r, post, control, dot.names) %>% 
               as.list) %>% 
        transpose %>% 
        pmap(., foo)
    #$Ellis.sh1
    #   n   r post control ESL prof scope type
    #1 13 0.5    1   FALSE   1    2     0    1
    #2 13 0.5    2   FALSE   1    2     0    1
    #3 15 0.5    1   FALSE   1    2     0    1
    #4 15 0.5    2   FALSE   1    2     0    1
    #5 16 0.5    1    TRUE   1    2     0    1
    #6 16 0.5    2    TRUE   1    2     0    1
    
    #$Goey1
    #   n   r post control ESL prof scope type
    #1 13 0.5    1   FALSE   0    1     1    0
    #2 13 0.5    2   FALSE   0    1     1    0
    #3 15 0.5    1   FALSE   0    1     1    0
    #4 15 0.5    2   FALSE   0    1     1    0
    #5 16 0.5    1    TRUE   0    1     1    0
    #6 16 0.5    2    TRUE   0    1     1    0
    
    #$kabla
    #   n   r post control ESL prof scope type
    #1 13 0.5    1   FALSE   1    3     0    1
    #2 13 0.5    2   FALSE   1    3     0    1
    #3 13 0.5    3   FALSE   1    3     0    1
    #4 15 0.5    1   FALSE   1    3     0    1
    #5 15 0.5    2   FALSE   1    3     0    1
    #6 15 0.5    3   FALSE   1    3     0    1
    #7 16 0.5    1    TRUE   1    3     0    1
    #8 16 0.5    2    TRUE   1    3     0    1
    #9 16 0.5    3    TRUE   1    3     0    1
    

    更新

    基于here的例子,结构略有不同,所以我们可以将listnames转置(对于base R

    argsT <- setNames(lapply(names(args[[1]]), 
          function(nm) lapply(args, `[[`, nm)), names(args[[1]]))
    
    
    out1 <- unname(do.call(Map, c(f = d.prepos, argsT)))
    out2 <- unname(do.call(Map, c(f = d.prepos, purrr::transpose(args))))
    identical(out1, out2)
    #[1] TRUE
    

    【讨论】:

    • rnorouzian 在THIS DATA 中的函数是d.prepos。他的代码是这样的:D &lt;- read.csv("https://raw.githubusercontent.com/izeh/i/master/k.csv", h = T) ; m &lt;- split(D, D$study.name) ; m[[1]] &lt;- NULL; ar &lt;- formalArgs(d.prepos); dot.names &lt;- names(m[[1]])[!names(m[[1]]) %in% ar]; args &lt;- lapply(m, function(x) unclass(x[c(head(ar, -1), dot.names)])); argsT &lt;- setNames(lapply(names(args[[1]]), function(i) lapply(args, [[, i)), names(args[[1]])); do.call(Map, c(f = d.prepos, argsT))
    • 当然,没问题。
    • 能否请您在此处粘贴您的完整解决方案?
    • @Reza 我觉得这很混乱。你能问一个新问题吗
    • 我的问题是HERE
    猜你喜欢
    • 1970-01-01
    • 2022-01-23
    • 2023-02-01
    • 2011-04-19
    • 1970-01-01
    • 2012-06-17
    • 2016-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多