创建一个增加的向量,但考虑另一个向量中相等元素的出现次数

时间:2014-08-02 03:42:48

标签: arrays matlab

我有一个看起来像这样的数组:

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

有谁知道这样做的优雅方式?非常感谢!

3 个答案:

答案 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,......从那里开始构建结果。