2016-05-01 2 views
0

Предположим, что у меня есть следующий массив:Среднее значение MATLAB, соответствующее каждому номеру столбца в матрице?

A=[1 2 
    1 4 
    2 6 
    3 5 
    5 7 
    1 9 
    2 7]; 

Что является наиболее эффективным (предпочтительно один вкладыш) способ в MATLAB, чтобы автоматически получить матрицу, которая держит среднее значение вторых элементов столбцов для каждого уникального элемента первая колонка? Результатом для A выше было бы:

B=[1 mean([2 4 9]) 
    2 mean([6 7]) 
    3 mean([5]) 
    5 mean([7])]; 

Заранее благодарим за внимание!

ответ

1

unique может генерировать первый столбец в то время как мощный accumarray оснащен функцией mean будет вычислять второе (nonzeros вызывается для несуществующих индексов, как 4 в данном случае):

>> B = [unique(A(:,1)),nonzeros(accumarray(A(:,1),A(:,2),[],@mean))] 
B = 
    1.0000 5.0000 
    2.0000 6.5000 
    3.0000 5.0000 
    5.0000 7.0000 

Как отмечалось в комментариях от dan-man, вышеупомянутый подход работает только в том случае, если первый столбец всегда имеет целочисленные значения (я предполагаю, что я использовал этот прецедент из данного примера; Извинения). Вы можете использовать unique, чтобы обойти недостаток следующим образом:

[Aunq,~,Aind] = unique(A(:,1)); 
B = [Aunq,accumarray(Aind,A(:,2),[],@mean))]; 

Далее отметил тот факт, что из-за того, как accumarray работает внутри, вызывая mean непосредственно не так эффективно, как выполнять вычисления более непосредственно:

B = [Aunq,accumarray(Aind,A(:,2),[],@sum)./accumarray(Aind,1,[],@sum)] 
+0

'accumarray' будет терпеть неудачу, если' A (:, 1) 'содержит что-либо, кроме небольших положительных целых чисел. Но вы можете легко обойти эту проблему, заменив 'A (:, 1)', третьим выходом 'unique (A (:, 1))'. И затем вы также можете отказаться от вызова «nonzeros». –

+0

Кроме того, если важна производительность, я рекомендую заменить 'accumarray (... @ mean)' на 'accumarray (..., @ sum) ./ accumarray (... 1, [], @ sum)', то есть вычислить суммировать и подсчитывать и делить вручную. В прошлый раз, когда я проверял, это было намного быстрее, потому что 'accumarray' не оптимизирован для использования с' @ mean'. –

+0

@ dan-man Ничего себе. Спасибо за советы. Я обновлю ответ. – TroyHaskin

0
B=[];for k=unique(A(:,1)).';B=[B;k sum((A(:,1)==k).*A(:,2))/sum((A(:,1)==k))];end 
Смежные вопросы