简体   繁体   English

与列表或向量输出等效的“外部”

[英]Equivalent of `outer` with list or vector output

With map you can apply a function to each pair of arguments : 使用map您可以将函数应用于每对参数:

> mapply(rep, 1:4, 4:1)
[[1]]
[1] 1 1 1 1

[[2]]
[1] 2 2 2

[[3]]
[1] 3 3

[[4]]
[1] 4

I expected to do something similar but for each combination of arguments with outer but it does not work because the output of outer should be a 4x4 array in this example : 我希望做同样的事情,但对于带参数的每个组合outer ,但它不工作,因为输出outer应在本例中,4×4阵列:

> outer(1:4, 4:1, rep)
Error in dim(robj) <- c(dX, dY) : 
  dims [produit 16] ne correspond pas à la longueur de l'objet [40]

Is there some R function (base R ideally) to do this as easily as mapply or outer ? 有一些一个R函数(基础R理想地)为做到这一点那样容易mapply还是outer

The expected output in this minimal example should look like this : 这个最小示例中的预期输出应如下所示:

> c(mapply(rep, 1:4, 4), mapply(rep, 1:4, 3), mapply(rep, 1:4, 2), mapply(rep, 1:4, 1))
 [1] 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 1 1 1 2 2 2 3 3 3 4 4 4 1 1 2 2 3 3 4 4 1 2 3 4
# Or
> c(rep(1:4, each = 4), rep(1:4, each = 3), rep(1:4, each = 2), rep(1:4, each = 1))
 [1] 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 1 1 1 2 2 2 3 3 3 4 4 4 1 1 2 2 3 3 4 4 1 2 3 4

I could use a combination of expand.grid and apply but I expect that there is some easier solution : 我可以结合使用expand.gridapply但是我希望有一些更简单的解决方案:

> unlist(apply(expand.grid(1:4, 4:1), 1, function(x) rep(x[1], x[2])))
Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 
   1    1    1    1    2    2    2    2    3    3    3    3    4    4    4    4    1    1 
Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 Var1 
   1    2    2    2    3    3    3    4    4    4    1    1    2    2    3    3    4    4 
Var1 Var1 Var1 Var1 
   1    2    3    4 

Based on 李哲源 Zheyuan Li' reply (for the record) : with outer and Vectorize you obtain a unusual object : a matrix with each element being a list : 基于李哲源李宋哲元”回复(备案):用outerVectorize获得一个不寻常的对象:其中每个元素列表中的矩阵:

> res <- outer(1:4, 4:1, Vectorize(rep.int))
> class(res)
[1] "matrix"
> typeof(res)
[1] "list"
> res
     [,1]      [,2]      [,3]      [,4]
[1,] Integer,4 Integer,3 Integer,2 1   
[2,] Integer,4 Integer,3 Integer,2 2   
[3,] Integer,4 Integer,3 Integer,2 3   
[4,] Integer,4 Integer,3 Integer,2 4   

You can unlist it to obtain a vector or remove the dimension attribute to obtain a regular list : 您可以unlist其取消unlist以获得向量,也可以删除Dimension属性以获得常规列表:

> unlist(res)
 [1] 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 1 1 1 2 2 2 3 3 3 4 4 4 1 1 2 2 3 3 4 4 1 2 3 4
> 
> dim(res) <- NULL
> # res <- c(res)  # equivalent
> res[1:5] # show the first 5 elements of the list
[[1]]
[1] 1 1 1 1

[[2]]
[1] 2 2 2 2

[[3]]
[1] 3 3 3 3

[[4]]
[1] 4 4 4 4

[[5]]
[1] 1 1 1

In this case outer(1:4, 4:1, Vectorize(rep.int)) works but in many situations you will need outer(1:4, 4:1, Vectorize(rep.int, SIMPLIFY = TRUE)) . 在这种情况下outer(1:4, 4:1, Vectorize(rep.int))可以工作,但是在许多情况下,您将需要outer(1:4, 4:1, Vectorize(rep.int)) outer(1:4, 4:1, Vectorize(rep.int, SIMPLIFY = TRUE)) See 李哲源 Zheyuan Li answer for more explanations 有关更多说明,请参见李哲源Zheyuan Li答案

Here, the output of myfun is a length 2 vector --> works only with SIMPLIFY = FALSE because you need that the result of each run of myfun is a length 1 list 在这里,myfun的输出是长度为2的向量->仅与SIMPLIFY = FALSE因为您需要每次运行myfun的结果都是长度为1的列表

> myfun <- function(x, y) c(sum(x,y), mean(x,y))
> myfun(1,4)
[1] 5 1
> res <- outer(1:4, 4:1, Vectorize(myfun, SIMPLIFY = TRUE))
Error in dim(robj) <- c(dX, dY) : 
  dims [produit 16] ne correspond pas à la longueur de l'objet [32]
> res <- outer(1:4, 4:1, Vectorize(myfun, SIMPLIFY = FALSE))
> 

Here the output of myfun is a length 2 list --> works only with SIMPLIFY = FALSE 这里myfun的输出是一个长度为2的列表->仅适用于SIMPLIFY = FALSE

> myfun <- function(x, y) list(sum(x,y), mean(x,y))
> myfun(1,4)
[[1]]
[1] 5

[[2]]
[1] 1

> res <- outer(1:4, 4:1, Vectorize(myfun, SIMPLIFY = TRUE))
Error in dim(robj) <- c(dX, dY) : 
  dims [produit 16] ne correspond pas à la longueur de l'objet [32]
> res <- outer(1:4, 4:1, Vectorize(myfun, SIMPLIFY = FALSE))
> 

Here the output of myfun is a length 1 list containing a length 2 vector --> works with both SIMPLIFY = FALSE and SIMPLIFY = TRUE 这里myfun的输出是一个长度为1的列表,其中包含一个长度为2的向量->与SIMPLIFY = FALSESIMPLIFY = TRUE

> myfun <- function(x, y) return(list(c(sum(x,y),mean(x,y))))
> myfun(1,4)
[[1]]
[1] 5 1

> res <- outer(1:4, 4:1, Vectorize(myfun, SIMPLIFY = TRUE))
> res <- outer(1:4, 4:1, Vectorize(myfun, SIMPLIFY = FALSE))

Just use FUN = Vectorize(rep.int, SIMPLIFY = FALSE) inside outer , to get a matrix list. 只需使用FUN = Vectorize(rep.int, SIMPLIFY = FALSE)outer ,以获得矩阵列表。

Related: How to perform pairwise operation like `%in%` and set operations for a list of vectors 相关: 如何执行成对操作(如“%in%”)并设置向量列表的操作

If we need an option with Map 如果我们需要Map选项

unlist(do.call(Map, c(f= rep, unname(expand.grid(1:4, 4:1)))))
#[1] 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 1 1 1 2 2 2 3 3 3 4 4 4 1 1 2 2 3 3 4 4 1 2 3 4

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM