相当于`outer`与列表或向量输出

时间:2017-06-20 08:39:29

标签: r vectorization

使用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

我希望对outer的每个参数组合执行类似的操作,但它不起作用,因为在此示例中outer的输出应为4x4数组:

> 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]

是否有一些R功能(理想情况下是基础R)可以像mapplyouter一样轻松完成这项工作?

此最小示例中的预期输出应如下所示:

> 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

我可以使用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 

基于李哲源Zheyuan Li&#39;回复(记录):使用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   

您可以unlist获取向量或删除维度属性以获取常规列表:

> 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

在这种情况下,outer(1:4, 4:1, Vectorize(rep.int))有效但在许多情况下您需要outer(1:4, 4:1, Vectorize(rep.int, SIMPLIFY = TRUE))。 有关更多说明,请参阅李哲源 Zheyuan Li answer

这里,myfun的输出是长度为2的向量 - &gt;仅适用于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))
> 

这里myfun的输出是长度为2的列表 - &gt;仅适用于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))
> 

这里myfun的输出是长度为1的列表,包含长度为2的向量 - &GT;适用于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))

2 个答案:

答案 0 :(得分:2)

只需在FUN = Vectorize(rep.int, SIMPLIFY = FALSE)中使用outer即可获得矩阵列表。

相关:How to perform pairwise operation like `%in%` and set operations for a list of vectors

答案 1 :(得分:2)

如果我们需要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