expand.grid和mapply的组合? [英] combination of expand.grid and mapply?
问题描述
我正在尝试提出mapply
的变体(现在称为xapply
),该变体结合了expand.grid
和mapply
的功能(某种).也就是说,对于函数FUN
和参数L1
,L2
,L3
,...的列表,长度未知的,它应生成长度为n1*n2*n3
的列表(其中ni
是列表i
的长度),这是将FUN
应用于列表元素的所有组合的结果.
I am trying to come up with a variant of mapply
(call it xapply
for now) that combines the functionality (sort of) of expand.grid
and mapply
. That is, for a function FUN
and a list of arguments L1
, L2
, L3
, ... of unknown length, it should produce a list of length n1*n2*n3
(where ni
is the length of list i
) which is the result of applying FUN
to all combinations of the elements of the list.
如果expand.grid
用来生成列表列表而不是数据框架,则可能可以使用它,但是我要记住,列表可能是不一定很好地适合数据框架的事物的列表
If expand.grid
worked to generate lists of lists rather than data frames, one might be able to use it, but I have in mind that the lists may be lists of things that won't necessarily fit into a data frame nicely.
如果恰好有三个要扩展的列表,则此功能正常运行,但我对更通用的解决方案感到好奇. (FLATTEN
未使用,但我可以想象FLATTEN=FALSE
会生成嵌套列表,而不是单个列表...)
This function works OK if there are exactly three lists to expand, but I am curious about a more generic solution. (FLATTEN
is unused, but I can imagine that FLATTEN=FALSE
would generate nested lists rather than a single list ...)
xapply3 <- function(FUN,L1,L2,L3,FLATTEN=TRUE,MoreArgs=NULL) {
retlist <- list()
count <- 1
for (i in seq_along(L1)) {
for (j in seq_along(L2)) {
for (k in seq_along(L3)) {
retlist[[count]] <- do.call(FUN,c(list(L1[[i]],L2[[j]],L3[[k]]),MoreArgs))
count <- count+1
}
}
}
retlist
}
编辑:忘记返回结果.也许可以通过使用combn
列出索引并从那里开始...
edit: forgot to return the result. One might be able to solve this by making a list of the indices with combn
and going from there ...
推荐答案
我认为我对自己的问题有解决方案,但也许有人可以做得更好(而且我还没有实现FLATTEN=FALSE
...)>
I think I have a solution to my own question, but perhaps someone can do better (and I haven't implemented FLATTEN=FALSE
...)
xapply <- function(FUN,...,FLATTEN=TRUE,MoreArgs=NULL) {
L <- list(...)
inds <- do.call(expand.grid,lapply(L,seq_along)) ## Marek's suggestion
retlist <- list()
for (i in 1:nrow(inds)) {
arglist <- mapply(function(x,j) x[[j]],L,as.list(inds[i,]),SIMPLIFY=FALSE)
if (FLATTEN) {
retlist[[i]] <- do.call(FUN,c(arglist,MoreArgs))
}
}
retlist
}
编辑:我尝试了@baptiste的建议,但这并不容易(或者对我而言并非如此).我最接近的是
edit: I tried @baptiste's suggestion, but it's not easy (or wasn't for me). The closest I got was
xapply2 <- function(FUN,...,FLATTEN=TRUE,MoreArgs=NULL) {
L <- list(...)
xx <- do.call(expand.grid,L)
f <- function(...) {
do.call(FUN,lapply(list(...),"[[",1))
}
mlply(xx,f)
}
仍然不起作用. expand.grid
确实比我想象的要灵活(尽管它创建了一个无法打印的怪异数据框),但是mlply
内部发生了很多不可思议的魔术.
which still doesn't work. expand.grid
is indeed more flexible than I thought (although it creates a weird data frame that can't be printed), but enough magic is happening inside mlply
that I can't quite make it work.
这是一个测试用例:
L1 <- list(data.frame(x=1:10,y=1:10),
data.frame(x=runif(10),y=runif(10)),
data.frame(x=rnorm(10),y=rnorm(10)))
L2 <- list(y~1,y~x,y~poly(x,2))
z <- xapply(lm,L2,L1)
xapply(lm,L2,L1)
这篇关于expand.grid和mapply的组合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!