首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从R中的CSV文件读取`.‘中定义的函数输入值

从R中的CSV文件读取`.‘中定义的函数输入值
EN

Stack Overflow用户
提问于 2019-06-22 17:33:35
回答 2查看 143关注 0票数 4

假设下面有一个类似于foo的R函数。这个函数有4个固定参数,以及在...中定义的任意数量的参数。

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

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

代码语言:javascript
复制
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?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-22 18:10:30

我们也可以将Mapdo.call结合使用。我们可以在对foo的单个调用中提取lapply的参数,方法是根据‘dot.name’的输出提取列'n‘、'r’、'post‘、控制和额外列(...),然后从transpose (来自purrr --或者使用与提到的这里相同的方法)将其传递给Map

代码语言:javascript
复制
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提到了用一个transpose选项替换base R

代码语言:javascript
复制
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

代码语言:javascript
复制
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

更新

基于示例显示的这里,结构略有不同,因此我们可以将list转换为names (对于base R)。

代码语言:javascript
复制
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
票数 5
EN

Stack Overflow用户

发布于 2019-06-22 18:03:08

对于这类问题,请使用mapply

在下面的代码中,我改变了您定义nrpostcontrol的方式。

代码语言:javascript
复制
n <- lapply(L, `[[`, 'n')
r <- lapply(L, `[[`, 'r')
post <- lapply(L, `[[`, 'post')
control <- lapply(L, `[[`, 'control')

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

然后还更改列表a的创建方式。交换这两个周期。

代码语言:javascript
复制
a <- lapply(L, function(i) lapply(dot.names, function(k) i[grep(k, names(i))]))

现在解决问题的办法。设置SIMPLIFY = FALSE是强制性的,默认的TRUE提供了非常糟糕的输出。

代码语言:javascript
复制
mapply(FUN = foo, n, r, post, control, a, SIMPLIFY = FALSE)
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56717677

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档