将省略号参数传递给map函数(purrr包,R语言)

4

我想在purrr包的map函数中使用省略参数。这是一个玩具示例:

f1<-function(x,a=NA,b=NA,prs=seq(0, 1, 0.25),SW=T){
  if(SW){
    res<-data.frame(name1=a,name2=b,t(quantile(x, prs, na.rm = T)),  mean=mean(x, na.rm = T), sd=sd(x, na.rm = T),
                    NAs=length(x[is.na(x)]),n=length(x[!is.na(x)]),SWp=shapiro.test(x)$p.value,stringsAsFactors =F)
  }else
  {
    res<-data.frame(name1=a,name2=b,t(quantile(x, prs, na.rm = T)),  mean=mean(x, na.rm = T), sd=sd(x, na.rm = T),
                    NAs=length(x[is.na(x)]),n=length(x[!is.na(x)]),stringsAsFactors =F)
  }
return(res)
}

f1(c(NA,rnorm(25),NA),SW=F)
f1(c(NA,rnorm(25),NA))

现在我想在另一个函数f2中使用f1:
f2<-function(df,...){
  res<-map_df(colnames(df),~f1(df[,.],a=.,...))
  return(res)
}

这里的...主要用于操作f1函数中的SW和a或b参数。然而,可以从这里看到,f2并没有做我想要的事情。

f2(iris[,-5])
f2(iris[,-5],SW=F)

我很感谢任何有关如何在地图中适当使用...的指导

4个回答

7

您只需通过将省略号传递给map_df()调用即可。否则它们无法进入内部的f1()调用。

f2 <- function(df, ...){
  res <- map_df(colnames(df), ~f1(df[,.], a=., ...), ...)
  return(res)
}

你可能还需要将省略号传递到匿名函数本身中,这样你就不是使用 ~,而是实际拼写出 function(.x, ...) 并且在你的函数序列中到处替换 ..x - dmi3kno
我同意@dmi3kno的观点,我认为需要使用function(.x, ...)结构!请查看我的帖子,谢谢! - Matifou

1
你也可以在第二个函数中早期捕获省略号,并使用do.call将它们稍后添加到第一个函数中。这样更明确地说明它们在哪里以及如何使用。
f2 <- function(df, ...){
  params <- list(...)
  res <- map_df(colnames(df), ~ do.call(
    f1, c(list(x = df[,.], a=.), params)))
  return(res)
}

1

MrFlick的解决方案对我没有用:我认为你确实需要将...传递给匿名函数,这就需要使用function(x,...)而不是~(正如@dmi3kno所建议的)。

这意味着你需要使用相当令人惊讶的三个...调用:

map(x, function(x, ...) mean(x, trim=0, ...), ...)

例子:

library(purrr)
x <- list(c(1,2), c(1,2,NA))
fo1 <- function(...) map(x, ~mean(., trim=0, ...), ...)
fo2 <- function(...) map(x, function(x, ...) mean(x, trim=0, ...), ...)

fo1()
#> Warning in if (na.rm) x <- x[!is.na(x)]: the condition has length > 1 and only
#> the first element will be used

#> Warning in if (na.rm) x <- x[!is.na(x)]: the condition has length > 1 and only
#> the first element will be used
#> [[1]]
#> [1] 1.5
#> 
#> [[2]]
#> [1] 1.5

fo2()
#> [[1]]
#> [1] 1.5
#> 
#> [[2]]
#> [1] NA
fo2(na.rm=TRUE)
#> [[1]]
#> [1] 1.5
#> 
#> [[2]]
#> [1] 1.5

该内容创建于2020年11月16日,使用reprex package (v0.3.0)


0
针对这个问题,我发现使用rlang :: exec()结合匿名函数可以允许您在purrr :: map()中传递 ...,类似于以下代码:

f2 <- function(df, ...){
  res <- map(colnames(df), function(x) rlang::exec("f1", df[,x], ...))
  return(res)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接