我有三个数字向量包含位置值(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
任何空条目都可以用零填充。
是否有简洁或快速的方式来做到这一点?
修改:
编辑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
在这种情况下,脚本完美运行:
答案 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