Краткий ответ - нет. В справке accumarray()
ключевая часть:
"VAL должен быть числовым, логическим или символьным вектором одинаковой длины
как количество строк в SUBS. VAL также может быть скаляром, значение которого
повторяется для всех рядов SUBS. "
Это означает, что вы даже не можете подделать его с помощью ячеек.
Однако, если вы поместите идентификаторы в их собственную индексную переменную, а затем измените свои данные таким образом, чтобы данные, соответствующие различным идентификаторам, находились в разных столбцах, эта проблема может быть эффективно обработана с помощью bsxfun()
. Для справки я также включил матричный математический метод, простой циклический метод for
, использующий cov()
, и метод cellfun()
, использующий пользовательскую функцию fncovariance()
(обратите внимание, я изменил его по сравнению с вашим выше).
fncovariance = @(x,y) mean(x.*y) - mean(x)*mean(y);
IDs = unique(mat1(:,1));
ret = reshape(mat1(:,2), sz, length(IDs));
idx = idx(1:sz, 2);
% bsxfun method
mean(bsxfun(@times, ret, idx)) - bsxfun(@times, mean(ret), mean(idx))
% matrix math
idx' * ret / length(idx) - mean(ret)*mean(idx)
% for loop method
id_cov = zeros(1, length(IDs));
for i=1:length(IDs)
tmp = cov(ret(:,i), idx, 1);
id_cov(i) = tmp(2,1);
end
id_cov
% cellfun method
ret_cell = num2cell(ret, 1);
idx_cell = num2cell(repmat(idx, 1, length(IDs)), 1);
cellfun(fncovariance, ret_cell, idx_cell)
Если вы смоделируете еще несколько данных и время этими разными методами, самый быстрый способ будет bsxfun()
:
sz = 10;
n_ids = 100;
IDs = 1:n_ids;
ret = randi(1000, sz, n_ids);
idx = randi(1000, sz, 1);
Elapsed time is 0.001292 seconds.
Elapsed time is 0.001523 seconds.
Elapsed time is 0.009625 seconds.
Elapsed time is 0.011454 seconds.
Последний вариант, который может вас заинтересовать, - это функция grpstats()
в наборе инструментов статистики, которая позволяет выкинуть произвольную статистику, основанную на переменной группировки.