使用多个索引向量计算相邻和非相邻对之间的差异

时间:2015-08-22 17:48:09

标签: arrays matlab indexing

我有三个数字向量包含位置值(pos),一个类别(type)和一个索引(ind),这些一般形式:

pos =
2 4 5 11 1 5 8 11 12 20

type = 
1 2 1 2 1 1 2 1 2 3

ind =
1 1 1 1 2 2 2 2 2 2

我想计算pos中保留的值之间的差异,但仅限于相同类型之间,并且仅限于每个索引。使用上面的例子:

当ind = 1

The difference(s) between type 1 positions = 3 (5-2). 
The difference(s) between type 2 positions = 7 (11-4).

如果任何索引中存在任何给定类型的两个以上实例,则差异按从左到右的顺序计算,如下所示:

当ind = 2

The difference(s) between type 1 positions = 4 (5-1), 6 (11-5).
The difference(s) between type 2 positions = 4 (12-8).

即使索引2包含类型' 3',也不会计算差异,因为只存在此类型的1个实例。

类型并不总是只有1,2或3.

理想情况下,所需的输出将是包含与length(unique(type))相同数量的列的矩阵,其中行包含为该类型计算的所有差异。输出不需要按索引分开,只需要实际计算。在这种情况下,有三种独特的类型,因此输出将是(仅为清晰起见而添加标签):

Type 1  Type 2  Type 3
  3       7       0
  4       4       0
  6       0       0

任何空条目都可以用零填充。

是否有简洁或快速的方式来做到这一点?

修改

enter image description here

编辑2:

附加输入/输出示例。

pos = [1 15 89 120 204 209 8 43 190 304]
type = [1 1 1 2 2 1 2 3 2 3]
ind = [1 1 1 1 1 1 2 2 2 2]

期望的输出:

Type 1  Type 2  Type 3
  14      84     261
  74      182     0
  120      0      0

在这种情况下,脚本完美运行:

enter image description here

1 个答案:

答案 0 :(得分:2)

至少在创建输出矩阵时需要一个循环:

pos = [2 4 5 11 1 5 8 11 12 20]
type = [1 2 1 2 1 1 2 1 2 3]
ind = [1 1 1 1 2 2 2 2 2 2]

%// get unique combinations of type and ind
[a,~,subs] = unique( [type(:) ind(:)] , 'rows')
%// create differences
%// output is cell array according to a
temp = accumarray(subs,1:numel(subs),[],@(x) {abs(diff(pos(x(end:-1:1))))} )

%// creating output matrix
for ii = 1:max(a(:,1))              %// iterating over types
    vals = [temp{ a(:,1) == ii }];  %// differences for each type
    out(1:numel(vals),ii) = vals;
end
out =

     3     7     0
     4     4     0
     6     0     0

如果它不适用于您的真实数据,您可能需要unique(...,'rows','stable')'stable' accumarray

上述解决方案似乎根据系统提供了不同的结果。

为什么代码可以在不同的机器上提供不同的结果,唯一的原因是 accumarray不是如上所述的稳定" 。在一些非常罕见的情况下,它可能会返回不可预测的结果。所以请尝试以下方法:

pos =  [2 4 5 11 1 5 8 11 12 20]
type = [1 2 1  2 1 1 2  1  2  3]
ind =  [1 1 1  1 2 2 2  2  2  2]

%// get unique combinations of type and ind
[a,~,subs] = unique( [type(:) ind(:)] , 'rows')

%// take care of unstable accumarray
[~, I] = sort(subs);
pos = pos(I);
subs = subs(I,:);

%// create differences
%// output is cell array according to a
temp = accumarray(subs,1:numel(subs),[],@(x) {abs(diff(pos(x(end:-1:1))))} )

%// creating output matrix
for ii = 1:max(a(:,1))              %// iterating over types
    vals = [temp{ a(:,1) == ii }];  %// differences for each type
    out(1:numel(vals),ii) = vals;
end
out =

     3     7     0
     4     4     0
     6     0     0