索引的Matlab矩阵和向量排序

时间:2015-03-08 21:12:51

标签: matlab sorting matrix

我有一个矩阵,其行代表音乐笔记。 [A,A#,B,C,C#,d,d#,E,F,F#,G,G#] 所以索引1代表A,2代表A#,依此类推。在矩阵中,索引中元素越大,音频中出现的可能性就越大。

我想计算在可能的12之间最常出现的3个索引。

这就是我推理的原因。首先,我使用[B,I] = sort()对每列进行排序。 B现在包含已排序的列 我现在包含以升序方式排序的索引。

因此我[10],我[11]和我[12]现在包含该列中的3个最大索引。

现在我创建一个名为notes的新向量。如果特定音符在排序时发现自己在I的最大3个索引中,那么相应的音符应该递增。

我正在尝试前3列,这些是:

0.0690   0.0530   0.0656
0.2453   0.2277   0.2306
0.0647   0.0315   0.0494
1.2037   1.1612   1.1613
0.0772   0.0346   0.0367
0.1628   0.1429   0.1648
0.0572   0.0370   0.0493
0.4119   0.3577   0.3635
0.0392   0.0430   0.0466
0.1182   0.0921   0.0935
0.7473   0.6680   0.7088
0.0794   0.0527   0.0566

因此,在第一次循环迭代的B中我应该得到,

 0.0392
 0.0572
 0.0674
 0.0690
 0.0772
 0.0794
 0.1182
 0.1628
 0.2453
 0.4119
 0.7473
 1.2037
我得到了(所以到现在为止一切都好)。 I(包含已排序的索引)也正确返回,其中3个最大的索引是8,11,4(即包含最大元素的原始索引,其中8,11,4按升序排列)

问题在if条件范围内。在第一次迭代中,在if条件之后,'notes'列向量应该在第8位,第11位,第4位增加。

0 
0 
0 
1 
0 
0 
0 
1 
0 
0 
1 
0 

然而,在if条件之后,仅向量中的第4个位置递增。实际上在第一次迭代之后,当显示'notes'向量时,我得到了

 0
 0
 0
 1
 0
 0
 0
 0
 0
 0
 0
 0

这是代码:

for col = 1:3        
    [B,I] = sort(C(:,col), 'ascend'); %B is the sorted column. I is the sorted indexes
    fprintf('Col No:');
    disp(col);
    fprintf('Sorted Column: ');
    disp(B);
    fprintf('Sorted Indexes: ');
    disp(I);

    if (I(10) == 1 || I(11) == 1 || I(12) == 1)
        notes(1,:) = notes(1,:) + 1;
    elseif (I(10) == 2 || I(11) == 2 || I(12) == 2)
        notes(2,:) = notes(2,:) + 1;
    elseif (I(10) == 3 || I(11) == 3 || I(12) == 3)
        notes(3,:) = notes(3,:) + 1;
    elseif (I(10) == 4 || I(11) == 4 || I(12) == 4)
        notes(4,:) = notes(4,:) + 1;
    elseif (I(10) == 5 || I(11) == 5 || I(12) == 5)
        notes(5,:) = notes(5,:) + 1;
    elseif (I(10) == 6 || I(11) == 6 || I(12) == 6)
        notes(6,:) = notes(6,:) + 1;
    elseif (I(10) == 7 || I(11) == 7 || I(12) == 7)
        notes(7,:) = notes(7,:) + 1;
    elseif (I(10) == 8 || I(11) == 8 || I(12) == 8)
        notes(8,:) = notes(8,:) + 1;
    elseif (I(10) == 9 || I(11) == 9 || I(12) == 9)
        notes(9,:) = notes(9,:) + 1;
    elseif (I(10) == 10 || I(11) == 10 || I(12) == 10)
        notes(10,:) = notes(10,:) + 1;
    elseif (I(10) == 11 || I(11) == 11 || I(12) == 11)
        notes(11,:) = notes(11,:) + 1;
    elseif (I(10) == 12 || I(11) == 12 || I(12) == 12)
        notes(12,:) = notes(12,:) + 1;

    end

    disp(notes);

我做错了什么?代码可能是错误的(或者可能更好)。我对Matlab并不擅长。这是第一次使用它。

非常感谢您的想法,意见和更正。

感谢您提前的时间

1 个答案:

答案 0 :(得分:2)

你好像是在思考这个问题。您可以使用sort并单独将排序应用于每列。 sort函数使用第二个参数来告诉您要应用排序的维度。如果要对列进行排序,则需要将第二个参数设置为1,这意味着您要对每列的行进行排序。

因此,定义"注释"的矩阵C

C = [0.0690   0.0530   0.0656
0.2453   0.2277   0.2306
0.0647   0.0315   0.0494
1.2037   1.1612   1.1613
0.0772   0.0346   0.0367
0.1628   0.1429   0.1648
0.0572   0.0370   0.0493
0.4119   0.3577   0.3635
0.0392   0.0430   0.0466
0.1182   0.0921   0.0935
0.7473   0.6680   0.7088
0.0794   0.0527   0.0566];

你可以这样做:

[~,I] = sort(C, 1, 'descend')

'descend' flag以降序顺序对值进行排序。因此,I将是矩阵,其中每列告诉您每列的每个排序值的位置。因此,您只需获取I的前三行。

因此,如果我们显示I的前三行,我们会得到:

>> disp(I(1:3,:))

 4     4     4
11    11    11
 8     8     8

这是有道理的,对于每一列,我们分别在第4,11和8位找到了最高值。

现在,如果您想要计算上述矩阵中显示的那些位置,您可以非常简单地使用histcaccumarray

因此:

ind = I(1:3,:); %// Get the first three rows of the sorted indices
notes = histc(ind(:), 1:12); %// or
%notes = accumarray(ind(:), 1, [12 1]);

因此,对于notes我们得到:

notes =

     0
     0
     0
     3
     0
     0
     0
     3
     0
     0
     3
     0

因此,我们看到每列的索引4,8和11,因此我们应该每次将这些位置增加1。 histc计算发生事件的频率,因此我们可以自然地使用它并计算出我们看到4,8和11的次数,或者我们在{{1}的前三行看到的任何数字}。 I执行相同的操作,但accumarray是一个更通用的功能,它不仅可以将相同的容器中的内容添加到一起。 accumarray是更好的方法 - 特别是因为箱数不变。


作为对这篇文章的编辑,在您的评论中,您说您希望能够将其应用于18个列段。最好的办法可能是在某种循环中这样做。首先弄清楚我们拥有的18列中有多少段,然后将其置于循环中多次并更新我们的结果。在循环的每次迭代中,我们需要在矩阵中拉出正确的18列,并且在我们到达数组末尾之前不断获取18个块。

我们将结果放在另一个矩阵中,其中每列是每18个列段中最常出现的三个音符的结果。

这样的事情:

histc

numColumns = size(C, 2); %// Get total number of columns for matrix numSegments = ceil(numColumns / 18); %// Get total number of segments finalMatrix = zeros(12, numSegments); for idx = 1 : numSegments %// Make sure that when we get 18 chunks, we don't out of bounds if 18*idx > numColumns seg = C(:,(idx-1)*18 + 1 : end); else seg = C(:,(idx-1)*18 + 1 : 18*idx); end [~,I] = sort(seg, 1, 'descend'); ind = I(1:3,:); %// Get the first three rows of the sorted indices notes = histc(ind(:), 1:12); %// Your code [~,y] = sort(notes, 'descend'); finalvec = zeros(12,1); finalvec(y(1)) = 1; finalvec(y(2)) = 1; finalvec(y(3)) = 1; %// Place in final matrix finalMatrix(:, idx) = finalvec; end 会将每个18个片段的结果存储到一个列中,其中每列都是您在评论中写下的逻辑。