Ответ 1
Одним из решений является репликация индексов строк в labels
и добавление другого столбца индексов столбцов. Затем вы можете изменить X
на вектор столбца и применить accumarray
один раз:
labels = [repmat(labels(:),nCols,1) ... % Replicate the row indices
kron(1:nCols,ones(1,numel(labels))).']; % Create column indices
totals = accumarray(labels,X(:)); % I used "totals" instead of "means"
Как это работает...
A = accumarray(subs,val)
для вектора столбца subs
, а вектор val
работает, добавив число в val(i)
к итогу в строке subs(i)
в векторном столбце вывода A
. Однако subs
может содержать больше, чем просто индексы строк. Он может содержать индексы индексов для нескольких измерений для назначения значений на выходе. Эта функция позволяет обрабатывать ввод val
, который является матрицей, а не вектором.
Во-первых, вход для val
можно преобразовать в вектор-столбец, используя оператор operator > X(:)
. Далее, чтобы отслеживать, какой столбец на выходе должен быть размещен, значения в X(:)
, мы можем изменить ввод subs
, чтобы включить дополнительный индекс столбца. Чтобы проиллюстрировать, как это работает, я буду использовать эти вводные данные:
labels = [3; 1; 1];
X = [1 2 3; ...
4 5 6; ...
7 8 9];
nCols = 3
И вот какие переменные в приведенном выше коде выглядят так:
labels = 3 1 X(:) = 1 totals = 11 13 15
1 1 4 0 0 0
1 1 7 1 2 3
3 2 2
1 2 5
1 2 8
3 3 3
1 3 6
1 3 9
Обратите внимание, например, что значения 1 4 7
, которые изначально были в первом столбце X
, будут накапливаться только в первом столбце вывода, как это обозначают те, что указаны в первых трех строках второго столбец labels
. Результирующий результат должен быть таким же, как вы получили бы, используя код в вопросе, где вы выполняете цикл над каждым столбцом, чтобы выполнить накопление.