将向量的每个元素与 R 中的另一个向量组合

Posted

技术标签:

【中文标题】将向量的每个元素与 R 中的另一个向量组合【英文标题】:Combine each element of a vector with another vector in R 【发布时间】:2015-06-29 22:23:48 【问题描述】:

我有两个向量

x <- c(2, 3, 4)
y <- rep(0, 5)

我想得到以下输出:

> z
2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0

如何创建z?我曾尝试使用pastec,但似乎没有任何效果。我唯一能想到的是使用for(),它非常慢。我用谷歌搜索了这个,我确信解决方案就在那里,我只是没有找到正确的关键字。

更新: 用于基准测试:

使用 Nicola 的解决方案:

 > system.time(
+ precipitation <- `[<-`(numeric(length(x)*(length(y)+1)),seq(1,by=length(y)+1,length.out=length(x)),x)
+ )
user  system elapsed 
0.419   0.407   0.827 

这速度快得离谱!我必须说!有人可以向我解释一下吗?我的for() 我知道在R 中总是错误的,如果它完成的话,至少需要一天时间。

其他建议:

 > length(prate)
[1] 4914594
> length(empty)
[1] 207
> system.time(
+ precipitation <- unlist(sapply(prate, FUN = function(prate) c(prate,empty), simplify=FALSE))
+ )
user  system elapsed 
16.470   3.859  28.904 

我不得不杀了

len <- length(prate)
precip2 <- c(rbind(prate, matrix(rep(empty, len), ncol = len)))

15 分钟后。

【问题讨论】:

虽然没有@nicola那么快,但另一个选择是rep(x, each=length(y)+1)*c(1,y) y 由全零组成时,我进行了编辑以加快处理速度。 【参考方案1】:

由于某种原因,这似乎更快:

 unlist(t(matrix(c(as.list(x),rep(list(y),length(x))),ncol=2)))

上述解决方案是通用的,因为xy 都可以具有任何值。在 OP 的情况下,y 仅由 0 组成,这很快:

 `[<-`(numeric(length(x)*(length(y)+1)),seq(1,by=length(y)+1,length.out=length(x)),x)
 #[1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0

编辑

我意识到我一直很神秘,我编写的代码并不容易理解,尽管只有一行。我将详细解释第二种解决方案的作用。

首先,您注意到生成的向量将包含x 中包含的值加上y 中的零重复length(x) 次。所以总的来说,它将是length(x) + length(x)*length(y)length(x)*(length(y)+1) long。所以我们根据需要创建一个只有零的向量:

  res<-numeric(length(x)*(length(y)+1))

现在我们必须将x 值放入res。我们注意到x的第一个值占据了res的第一个值;第二个将在第一个之后的length(y)+1 之后,依此类推,直到填充所有length(x) 值。我们可以创建一个索引向量,将x 值放入其中:

  indices<-seq.int(1,by=length(y)+1,length.out=length(x))

然后我们进行替换:

  res[indices]<-x

我的行只是上面三行的捷径。希望这能澄清一点。

【讨论】:

您的解决方案是迄今为止最快的。我认为t 可能会降低速度,但它没有 是的,有趣的解决方案。 非常好的解决方案。您可以使用integer 而不是numeric 以使其更快。 另外seq.int 而不是seq 似乎更快。 ;) nicola 的解决方案基本上是x=1:1e5;y=rep(0,40);tmp=numeric(length(x)*(length(y)+1));tmp[seq(1,by=length(y)+1,length.out=length(x))]=x; 的简写。比较:all.equal([&lt;-(numeric(length(x)*(length(y)+1)),seq(1,by=length(y)+1,length.out=length(x )),x),tmp)【参考方案2】:

你可以试试这个

unlist(sapply(x, FUN = function(x) c(x,y), simplify=FALSE))
 [1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0

或更简单的@docendodiscimus

unlist(lapply(x, FUN = function(x) c(x,y)))

【讨论】:

你可以使用lapply所以你不需要指定simplify = FALSE 我没有尝试其他建议,但这非常快(大约需要 30 秒,而我的循环至少需要一天)。 @cddesjardins 如果您也测试其他答案的速度会很有趣。 并且可以在调用中添加 y,因此它不依赖 y 作为第二个向量的名称,从而导致: unlist (lapply(x, function(x, y) c(x ,y), y))【参考方案3】:

你也可以尝试如下矢量化

len <- length(x)
c(rbind(x, matrix(rep(y, len), ncol = len)))
## [1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0

一个更紧凑但可能更慢的选项(由@akrun 提供)是

c(rbind(x, replicate(len, y)))
## [1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0

【讨论】:

在 1e6 'x' 向量和长度为 100 的 'y' 上尝试了一些基准测试。使用dim&lt;- 更快一点,@Mamoun Benghezal 的解决方案首先出现,replicate 解决方案是最慢的,但比例为 1 与 2.9 @akrun 有趣。虽然很奇怪【参考方案4】:

你可以试试:

 c(sapply(x, 'c', y))
 #[1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 

或者使用 gusb 和粘贴的疯狂解决方案..

library(functional)
p = Curry(paste0, collapse='')

as.numeric(strsplit(p(gsub('(.*)$', paste0('\\1',p(y)),x)),'')[[1]])
#[1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0

【讨论】:

【参考方案5】:

这是另一种方式:

options(scipen=100)
as.numeric(unlist(strsplit(as.character(x * 10^5), "")))

还有一些基准测试:

microbenchmark(as.numeric(unlist(strsplit(as.character(x*10^5), ""))), unlist(t(matrix(c(as.list(x),rep(list(y),length(x))),ncol=2))), unlist(sapply(x, FUN = function(x) c(x,y), simplify=FALSE)), times=100000)
Unit: microseconds
                                                                        expr
                 as.numeric(unlist(strsplit(as.character(x * 10^5), ""))) 
      unlist(t(matrix(c(as.list(x), rep(list(y), length(x))), ncol = 2))) 
           unlist(sapply(x, FUN = function(x) c(x, y), simplify = FALSE)) 
   min     lq     mean median     uq       max  neval
 9.286 10.644 12.15242 11.678 12.286  1650.133 100000
 9.485 11.164 13.25424 12.288 13.067  1887.761 100000
 5.607  7.429  9.21015  8.147  8.784 30457.994 100000

这是另一个想法(但似乎很慢):

r = rle(1)
r$lengths = rep(c(1,5), length(x))
r$values =  as.vector(rbind(x, 0))
inverse.rle(r)

【讨论】:

基于 OP 帖子中的x,我得到as.numeric(unlist(strsplit(as.character(x * 10^5), ""))) #[1] 2 NA NA 0 5 3 NA NA 0 5 4 NA NA 0 5,这不是预期的结果 搞笑,我猜对了:as.numeric(unlist(strsplit(as.character(x * 10^5), ""))) [1] 2 0 0 0 0 0 3 0 0 0 0 0 4 0 0 0 0 0 @akrun 哦耶——关闭科学记数法:options(scipen=100)

以上是关于将向量的每个元素与 R 中的另一个向量组合的主要内容,如果未能解决你的问题,请参考以下文章

R中多个向量的组合

R中N个元素与q个元素的组合

组合列表中的向量以创建数据框 R [重复]

R语言的自定义函数—字符组合

R从n个元素的字符向量中生成大小为m的所有可能组合[重复]

向量与子向量长度 n 的组合