在参考 this question 时,我试图找出将函数列表应用于值列表的最简单方法。基本上,嵌套lapply
。例如,我们在此处将sd
和mean
应用于内置数据集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
但我希望也许有一种聪明的方法可以通过我缺少的位置和名称匹配来做到这一点。
答案 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)