Применить массив функций к матрице

У меня есть матрица M со строками, отсортированными по одному столбцу (скажем, c), т.е.:

M = sortrows(M,c)

Мне нужно применить функцию к каждой строке матрицы, и эта функция зависит от значения в столбце c, используемом для сортировки. Например, если столбец c является вектором [1 1 1 2 2 2 3 3 3 3 3]', мне нужно вызвать f1 для строк с 1 по 3, f2 для строк с 4 по 6 и f3 для строк с 7 по 11 в качестве аргументов.

Кроме того, я хочу вызывать каждую функцию со всеми строками, которые содержат одно и то же значение в столбце c, переданном в качестве аргумента, чтобы избежать использования слишком медленного цикла для строк. Есть ли (очень) быстрый способ сделать это? (если сортировка M не нужна, было бы еще лучше).

Спасибо.

Я уточняю свою потребность с помощью некоторого кода (M здесь не сортируется, поскольку кажется, что это не нужно):

function test  
M=zeros(4,2);  
c=2;  
M(1:2,2)=[3,6]';
M(3:5,2)=[1,3,1]';
M(6:10,2)=[3,6,1,6,3]';   

function res = f1(y1,y2)
res=[1,1,1];
end

function res = f3(y1,y2)
res=[2,2,2];
end

function res = f6(y1,y2)
res=[3,3,3];
end

У нас есть:

M =

 0     3
 0     6
 0     1
 0     3
 0     1
 0     3
 0     6
 0     1
 0     6
 0     3

Теперь каждая строка будет аргументом функции fi,i=1,...n, где i=значение в столбце c, т.е. в примере выше:

f3 со строками 1,4,6,10 в качестве аргументов, f1 со строками 3,5,8 в качестве аргументов и f6 со строками 2,7 и 9 в качестве аргументов.

Как я могу сделать это без использования циклов?


person Gilbert    schedule 14.07.2013    source источник


Ответы (1)


Нет необходимости сортировать строки M. Попробуйте accumarray с пользовательской функцией:

F = {@f1, @f2, @f3}; %// Cell array of function handles
result = accumarray(repmat(M(:, c), size(M, 2), 1), M(:), [], @(x)F{x(1, c)}(x));

Обратите внимание, что accumarray преобразует группы строк с одинаковым значением c в векторы-столбцы, поэтому вам придется изменить их форму обратно, если ваши функции не могут этого обработать. Для этого вы можете определить альтернативный набор функций, прежде чем передавать его в accumarray:

g = @(x)reshape(x, [], size(M, 2));
F = {@(x)f1(g(x)), @(x)f2(g(x)), @(x)f3(g(x))};
person Eitan T    schedule 14.07.2013
comment
В данный момент я не рядом с MATLAB, чтобы проверить это, надеюсь, я правильно понял синтаксис. - person Eitan T; 14.07.2013
comment
Спасибо, но я получаю сообщение об ошибке: ()-indexing должен стоять последним в выражении индекса - person Gilbert; 14.07.2013
comment
Я забыл упомянуть, что fi должен возвращать вектор, а не скаляр. Возможно ли это с accumarray? P.S. Я мог бы клонировать функцию, чтобы каждый клон возвращал каждый скалярный элемент вектора, но это означало бы вызов функции столько раз, сколько длина вектора, что медленно. - person Gilbert; 16.07.2013
comment
@Gilbert Да, я реализую это таким образом, когда у меня будет доступ к MATLAB. - person Eitan T; 16.07.2013
comment
@Gilbert Привет - извините за задержку - у меня еще не было времени решить проблему - я постараюсь найти время сегодня позже. С тобой все в порядке? - person Eitan T; 23.07.2013