我有一个看起来像这样的数组:
A =
5873 4
5873 7
5873 1
2819 8
2819 1
9771 4
9771 2
9771 5
9771 6
5548 7
我想要做的是创建一个新列,该列将命令放入数组中唯一标识符(即第一列中的条目)出现的时间。像这样:
B =
5873 4 1
5873 7 1
5873 1 1
2819 8 2
2819 1 2
9771 4 3
9771 2 3
9771 5 3
9771 6 3
5548 7 4
有谁知道这样做的优雅方式?非常感谢!
答案 0 :(得分:1)
我认为Matlab没有内置函数可以做到这一点,但你可以很容易地自己实现它:
B = [A zeros(size(A,1),1)]; %Preallocate memory
for i = 1:size(A,1)
B(i,3) = sum(A(:,1) == A(i,1)); %Count how many occurrences
end
这不是超级高效的,因为它会执行一堆冗余计算,但它会完成工作。另外,如果你开始使用非整数数据,要小心:从2013b开始,Matlab说语句0.1 + 0.1 + 0.1 == 0.3是假的(由于浮点怪癖)所以上面的代码可能会给出一些神秘的结果。
答案 1 :(得分:1)
在'stable'
- 模式中使用unique
的第三个输出:
[~,~,Y] = unique( A(:,1), 'stable')
B = [A Y]
给出:
B =
5873 4 1
5873 7 1
5873 1 1
2819 8 2
2819 1 2
9771 4 3
9771 2 3
9771 5 3
9771 6 3
5548 7 4
正如Luis Mendo指出的那样, Matlab 2013a 引入了'stable'
unique的选项。对于旧版本,我建议使用accumarray
的第一个想法:
%// count number of occurences and create vector of zeroes with the same length
%// but first element set to 1
X = accumarray(A(:,1),A(:,1),[],@(x) {[1 zeros(1, numel(x)-1) ]} )
%// reordering and cumulative sum gives the desired output vector
B = [A cumsum([X{:}])']
答案 2 :(得分:1)
answer by @thewaywewalk是要走的路。但是,如果您的Matlab版本不够新,unique
函数没有'stable'
选项。在这种情况下,您可以使用bsxfun
:
[~, e] = max(bsxfun(@eq, A(:,1), A(:,1).'));
k = cumsum([1 diff(e)] > 0);
B = [A k.'];
此操作如下:
对于A
第一列中的每个条目,向量e
给出该值第一次出现的索引(max
的第二个输出给出第一个< / em>最大化器的位置)。在您的示例中,e
为:1,1,1,4,4,6,...然后,向量k
将该序列转换为连续数字:1,1,1,2,2 ,3,......从那里开始构建结果。