我有三个向量,v1、v2、v3。我想得到的是每一对可能的它们之间的差异,即v1-v2、v1-v3、v2-v3。在matlab中,我如何在不循环的情况下做到这一点?
谢谢。
只需先使用nchoosek
生成组合,然后使用它们对行向量数组进行索引:
测试用例:
numVectors = 3;
dim = 5;
Vs = rand(numVectors, dim);
实际计算:
combs = nchoosek(1:size(Vs,1), 2);
differences = Vs(combs(:,1),:) - Vs(combs(:,2),:);
以上创建了3个维度为5的随机行向量。因此,在您的情况下,如果您的向量是行向量,您可能希望用Vs = [v1; v2; v3];
替换随机矩阵的创建;或者如果数据是列向量,则使用Vs = [v1, v2, v3].';
转置向量。
使用bsxfun
:
clear
clc
%// Sample vectors.
v1 = [1 2];
v2 = [10 20];
v3 = [0 0];
Out = bsxfun(@minus,[v1 v2 v3], [v1 v2 v3].')
Out =
0 1 9 19 -1 -1
-1 0 8 18 -2 -2
-9 -8 0 10 -10 -10
-19 -18 -10 0 -20 -20
1 2 10 20 0 0
1 2 10 20 0 0
推理:从第一个向量的第一个元素开始计算每个差值,直到最后一个向量的第二个元素。
第一列包含第一个向量的第一个元素的所有差,即(1-1)、(1-2)、(1-10)、(1-20)、(1-0)、(1/0)。
然后是第二列,同样的东西,但这次是2:(2-1),(2-2),(2-10),依此类推
对不起,如果我的解释不清楚,哈哈,我不知道正确的英语术语。请询问更多详细信息。
代码
%// Concatenate all vectors to form a 2D array
V = cat(2,v1(:),v2(:),v3(:),v4(:),v5(:))
N = size(V,2) %// number of vectors
%// Find all IDs of all combinations as x,y
[y,x] = find(bsxfun(@gt,[1:N]',[1:N])) %//'
%// OR [y,x] = find(tril(true(size(V,2)),-1))
%// Use matrix indxeing to collect vector data for all combinations with those
%// x-y IDs from V. Then, perform subtractions across them for final output
diff_array = V(:,x) - V(:,y)
关于代码的几点
bsxfun
与find
为我们获得了形成成对组合的ID- 我们使用这些ID索引到2D级联数组中,并在它们之间进行减法以获得最终输出
奖金
如果你仔细观察它找到所有组合的IDs
的部分,基本上就是nchoosek(1:..,2)
。
因此,基本上可以有nchoosek(1:N,2)
的替代品:
[Y,X] = find(bsxfun(@gt,[1:N]',[1:N]))
[y,x] = find(tril(true(N),-1))
[X Y]
形成了这些成对的组合,对它们进行基准测试可能很有趣!