【问题标题】:MATLAB: Fastest Way to Count Unique # of 2 Number Combinations in a Vector of IntegersMATLAB:计算一个整数向量中唯一的 2 个数字组合的最快方法
【发布时间】:2013-05-08 17:06:56
【问题描述】:

给定一个整数向量,例如:

X = [1 2 3 4 5 1 2]

我想找到一种非常快速的方法来计算具有 2 个元素的唯一组合的数量。

在这种情况下,两个数字的组合是:

[1 2] (occurs twice)
[2 3] (occurs once) 
[3 4] (occurs once) 
[4 5] (occurs once) 
[5 1] (occurs once) 

就目前而言,我目前在 MATLAB 中这样做如下

X = [1 2 3 4 5 1 2];
N = length(X)
X_max = max(X);
COUNTS = nan(X_max); %store as a X_max x X_max matrix

for i = 1:X_max

    first_number_indices   = find(X==1)
    second_number_indices = first_number_indices + 1;
    second_number_indices(second_number_indices>N) = [] %just in case last entry = 1
    second_number_vals = X(second_number_indices);

   for j = 1:X_max
        COUNTS(i,j) = sum(second_number_vals==j)
   end
end

有更快/更智能的方法吗?

【问题讨论】:

  • 如果有人感兴趣,我想到的应用程序如下:X 基本上是马尔可夫链中的示例路径,而 COUNTS 是创建转换矩阵的基本方法,以便归一化后,COUNTS(i,j) = P(next state = j | current state = i)。
  • 问得好,但我发现你陈述它的方式有点误导。您不想知道唯一组合的数量,即有多少种不同的组合,而是每个组合出现的次数。否则,unique(A, 'rows') 会成为你的朋友。

标签: matlab


【解决方案1】:

这是一个超级快速的方法:

>> counts = sparse(x(1:end-1),x(2:end),1)
counts =
   (5,1)        1
   (1,2)        2
   (2,3)        1
   (3,4)        1
   (4,5)        1

您可以简单地转换为完整矩阵:full(counts)


这是使用accumarray 的等效解决方案:

>> counts = accumarray([x(1:end-1);x(2:end)]', 1)
counts =
     0     2     0     0     0
     0     0     1     0     0
     0     0     0     1     0
     0     0     0     0     1
     1     0     0     0     0

【讨论】:

  • 哈哈,公平地说,这类问题经常出现(与马尔可夫链有关),并且经常引用sparse 解决方案:)
  • @Amro 你能想出比[ii, jj] = find(counts); pairs = [ii, jj]; counts = full(diag(counts(ii, jj)));更优雅的方式来获得正确形式的pairs/counts数组吗?
  • @EitanT:使用 find 的所有三个输出:[ii,jj,v] = find(counts)
  • @Amro 我一直忘记find 也可以自己返回元素:)
  • 非常好+1! sparse 的用处真大。我将来会自己使用它。但我认为如果X 包含零,它将不起作用?
【解决方案2】:

编辑: @Amro 提供了一个更好的解决方案(嗯,在绝大多数情况下更好,我怀疑如果 MaxX 非常大并且 X 包含zeros - 这是因为零的存在将排除 sparse 的使用,而较大的 MaxX 会减慢 accumarray 方法,因为它会创建一个大小为 MaxX x MaxX 的矩阵。

编辑:感谢@EitanT 指出可以使用accumarray 进行的改进。

这是我的解决方法:

%Generate some random data
T = 20;
MaxX = 3;
X = randi(MaxX, T, 1);

%Get the unique combinations and an index. Note, I am assuming X is a column vector.
[UniqueComb, ~, Ind] = unique([X(1:end-1), X(2:end)], 'rows');
NumComb = size(UniqueComb, 1);

%Count the number of occurrences of each combination
Count = accumarray(Ind, 1);

所有唯一的连续两个元素组合现在存储在UniqueComb,而每个唯一组合的相应计数存储在Count

【讨论】:

  • Count = accumarray(Ind, 1); 可能比使用循环计数要快。此外,您应该指出 X 必须是列向量,这样才能正确计算唯一行。
  • @EitanT 谢谢。我已将accumarray 合并到我的答案中。关于列向量问题,我在代码内的 cmets 中指出 X 需要是列向量。考虑到 Amro 出色的 sparse 方法,有点多余 :-)
猜你喜欢
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 2018-11-20
  • 2023-03-20
  • 2014-09-10
  • 1970-01-01
  • 1970-01-01
  • 2015-04-13
相关资源
最近更新 更多