【问题标题】:A similar function to R's rep in Matlab [duplicate]Matlab中与R的rep类似的功能[重复]
【发布时间】:2013-01-30 22:43:08
【问题描述】:

我正在寻找一个与 R for Matlab 中的 rep 函数类似的函数。例如使用rep,我可以执行以下操作:

> rep(c(1,2,3),times=3)
[1] 1 2 3 1 2 3 1 2 3

> rep(c(1,2,3),each=3)
[1] 1 1 1 2 2 2 3 3 3
> 

在matlab中有repmat函数完成第一部分

>> repmat([1,2,3],1,3)

ans =

     1     2     3     1     2     3     1     2     3

但不是第二部分(或者至少我不知道该怎么做)。

有什么建议吗?

【问题讨论】:

  • 不敢相信我不知道repeach 选项;一直在使用 hacky one-liner...
  • 请注意,自 Matlab 2015a 以来,现在有一个内置函数可以执行此操作:repelem

标签: r matlab


【解决方案1】:

您可以通过首先定义如下函数来相当接近地重现 R 中 rep 函数的语法:

function [result]=rep(array, count)
matrix = repmat(array, count,1);
result = matrix(:);

然后您可以通过使用行向量或列向量调用来重现所需的行为:

>> rep([1 2 3],3)
ans =
 1     1     1     2     2     2     3     3     3

>> rep([1 2 3]',3)
ans =
 1     2     3     1     2     3     1     2     3

注意,我在第二次调用中使用了转置 (') 运算符将输入数组作为列向量(3x1 矩阵)传递。

我在笔记本电脑上对此进行了基准测试,对于具有 100,000 个元素且重复 100 次的基本数组,它比使用上面的 ceil 选项快 2 到 8 倍,具体取决于您想要第一种排列还是第二种排列。

【讨论】:

  • 快速简单!我很惊讶 repmat 是赢家,但在这种情况下,它绝对是最好的解决方案!
  • 如果有效实施,repmat 应该非常快,因为它通过将内存从一个位置复制到另一个位置来执行重复。具有大量缓存的现代处理器非常擅长这种事情。这也是为什么两种使用类型之间存在 4 倍速度差异的原因:快速的一种具有跨度一内存访问,而另一种具有跨度长度(数组)内存访问,速度较慢。
【解决方案2】:

好问题+1。实现此目的的一种简洁的单线方法是通过 Kronecker 张量积,例如:

A = [1 2 3];
N = 3;
B = kron(A, ones(1, N));

然后:

B =

     1     1     1     2     2     2     3     3     3

更新: @Dan 提供了一个非常简洁的解决方案,看起来比我的 kron 方法更有效,所以在离开页面之前检查一下答案:-)

更新:@bcumming 还提供了一个很好的解决方案,当输入向量很大时应该可以很好地扩展。

【讨论】:

  • 我试图想出一个我能理解的解决方案,因为我不知道克罗内克张量积是什么。您可能对结果感兴趣,我认为它比 kron() 更快,尽管我还没有真正进行适当的基准测试...
【解决方案3】:

如果您像我一样不知道 Kronecker 张量积是什么,您可能会对这种更直观(实际上我认为更快)的解决方案感兴趣:

c(ceil((1:length(c)*n)/n));

所以在这里我使用向量索引来复制矩阵。例如,使用上面的两种情况,我们可以这样做:

c = 1:3;
c([1 1 1 2 2 2 3 3 3]) %for each
c([1 2 3 1 2 3 1 2 3]) %for times

所以问题是我们如何在没有您要求的功能的情况下制作向量 [1 2 3 1 2 3 1 2 3]。所以我用我们需要的元素数量制作了一个向量,即 1:9,然后除以三并四舍五入(即在命令行中尝试 ceil((1:9)/3)

一些基准测试(我知道这些东西应该在循环中,所以也许这不是那么准确):

c = 1:3; n = 3;
tic; k = kron(c, ones(1, n)); toc; % 0.000208 seconds.
tic; a = c(ceil((1:length(c)*n)/n)); toc;  % 0.000025 seconds.
clear;
c = 1:1000000; n = 3;
tic; k = kron(c, ones(1, n)); toc; % 0.143747 seconds.
tic; a = c(ceil((1:length(c)*n)/n)); toc;  % 0.090956 seconds.
clear;
c = 1:10000; n = 1000;
tic; k = kron(c, ones(1, n)); toc; % 0.583336 seconds.
tic; a = c(ceil((1:length(c)*n)/n)); toc;  % 0.237878 seconds.

【讨论】:

  • 非常整洁+1!我在我的机器上验证了你的速度测试并添加了一些循环,你得到的结果相当有代表性。通常,我发现您的方法比kron 快约 4 倍。更直观?我认为这是旁观者的看法 :-) Kronecker 产品在概念上非常简单,一旦完成了计算它们如何工作的初始成本......
  • 是的,很公平 - 我想这只是名字,它里面有张量这个词,所以它吓到我了 :)
  • 好吧,它在我的小例子中确实有效,但我想要一些真正适用于“不规则”向量的东西。例如,像 c = [1.34,9.2,-8.2,99] 这样的向量
  • 它适用于任何矢量,甚至是文本。它绝对适用于您评论中的矢量。它甚至可以解决这个问题:n=3; c = '哇!'; c(ceil((1:length(c)*n)/n))
【解决方案4】:

这里有一个想法:

a=[1,2,3];
reshape(repmat(a,1,length(a)),1,length(a)^2)

ans =

 1     2     3     1     2     3     1     2     3

reshape(repmat(a,length(a),1),1,length(a)^2)

ans =

 1     1     1     2     2     2     3     3     3

我还没有找到一个更简单的函数,可以一步完成,如果有的话。

【讨论】:

  • 有一个更简单的一步函数:kron(Kronecker 张量积)。我已经用一个例子添加了一个答案。干杯。
猜你喜欢
  • 2016-11-20
  • 2015-02-02
  • 2013-04-23
  • 1970-01-01
  • 2010-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多