将函数列表应用于值列表

时间:2015-06-10 14:29:45

标签: r apply

在参考 this question 时,我试图找出将函数列表应用于值列表的最简单方法。基本上,嵌套lapply。例如,我们在此处将sdmean应用于内置数据集trees

funs <- list(sd=sd, mean=mean)
sapply(funs, function(x) sapply(trees, x))

得到:

              sd     mean
Girth   3.138139 13.24839
Height  6.371813 76.00000
Volume 16.437846 30.17097

但是我希望避免使用内部function,并且有类似的内容:

sapply(funs, sapply, X=trees)

不起作用,因为X匹配第一个sapply而不是第二个functional::Curry。我们可以使用sapply(funs, Curry(sapply, X=trees))

来完成
#!/bin/bash

但我希望也许有一种聪明的方法可以通过我缺少的位置和名称匹配来做到这一点。

4 个答案:

答案 0 :(得分:25)

由于mapply使用省略号...来传递矢量(原子或列表)而不是sapply, lapply, etc ...中的命名参数(X),因此您不需要为参数命名X = trees如果你使用mapply而不是sapply:

funs <- list(sd = sd, mean = mean)

x <- sapply(funs, function(x) sapply(trees, x))

y <- sapply(funs, mapply, trees)

> y
              sd     mean
Girth   3.138139 13.24839
Height  6.371813 76.00000
Volume 16.437846 30.17097
> identical(x, y)
[1] TRUE

你差一点就能得到你想要的东西! :)

请注意,我使用了funs的列表,因为我无法创建函数的数据框,但我收到了错误。

> R.version.string
[1] "R version 3.1.3 (2015-03-09)"

答案 1 :(得分:14)

您基本上需要某种匿名函数,因为没有其他方法可以将命名参数区分为两个不同的sapply调用。您已经显示了明确的匿名函数和Curry方法。您也可以使用magrittr

 library(magrittr)
 sapply(funs, . %>%  sapply(trees, .))
 # or .. funs %>% sapply(. %>%  sapply(trees, .))

但关键是你需要某事来进行拆分。 &#34;问题&#34;是sapply发送给lapply这是internal function,它似乎决定将更改的值作为函数调用的开头。你需要一些东西来重新排序参数,并且由于相同的参数名称组,如果没有帮助函数来处理消歧,就不可能将它分开。

mapply功能允许您将列表传递给&#34; MoreArgs&#34;这允许一种方法来绕过命名参数冲突。这是为了在您应该向量化的项目和已修复的项目之间进行拆分。因此你可以做到

mapply(sapply, funs, MoreArgs=list(X=trees))
#               sd     mean
# Girth   3.138139 13.24839
# Height  6.371813 76.00000
# Volume 16.437846 30.17097

答案 2 :(得分:5)

使用purrr的另一种方法是:

require(purrr)

funs <- list(sd=sd, mean=mean)
trees %>% map_df(~invoke_map(funs, ,.), .id="id")

重要:请注意invoke_map的空第二个参数按位置匹配。请参阅?purrr::invoke_map示例。

给你:

Source: local data frame [3 x 3]

      id        sd     mean
   <chr>     <dbl>    <dbl>
1  Girth  3.138139 13.24839
2 Height  6.371813 76.00000
3 Volume 16.437846 30.17097

此方法不是使用rownames,而是为您提供包含原始列的列id

答案 3 :(得分:1)

虽然不像@ Floo0提供的解决方案那样具有启发性和优雅性,但这是使用tidyrdplyr的另一种观点:

+ root
|---child
|-----grandchild
|-----grandchild

这一系列操作在信号意图方面做得不错,但代价是额外的冗长。