Я хочу применить функцию ко всем столбцам в матрице с помощью MATLAB. Например, я хотел бы иметь возможность вызывать сглаживание для каждого столбца матрицы вместо сглаживания обработки матрицы как вектора (что является поведением по умолчанию, если вы вызываете smooth(matrix)).
Я уверен, что должен быть более идиоматический способ сделать это, но я не могу его найти, поэтому я определил функцию map_column:
function result = map_column(m, func)
result = m;
for col = 1:size(m,2)
result(:,col) = func(m(:,col));
end
end
с которым я могу вызвать:
smoothed = map_column(input, @(c) (smooth(c, 9)));
Что-то не так с этим кодом? Как я мог это улучшить?





Если это общий вариант использования вашей функции, возможно, было бы неплохо сделать так, чтобы функция автоматически перебирала столбцы, если входные данные не являются вектором.
Это не совсем решит вашу проблему, но упростит использование функций. В этом случае на выходе тоже должна быть матрица.
Вы также можете преобразовать матрицу в один длинный столбец с помощью m(:,:) = m(:). Однако это зависит от вашей функции, если это будет иметь смысл.
Возможно, вы всегда можете преобразовать матрицу с помощью оператора ', а затем преобразовать результат обратно.
smoothed = smooth(input', 9)';
По крайней мере, это работает с функцией fft.
' - это транспонированный комплексный конъюгат. Если цель состоит в том, чтобы поменять местами два измерения матрицы, используйте .'.Оператор MATLAB "for" фактически перебирает столбцы любого предоставленного - обычно это просто приводит к последовательности скаляров, поскольку вектор, переданный в for (как в вашем примере выше), является вектором-строкой. Это означает, что вы можете переписать приведенный выше код следующим образом:
function result = map_column(m, func)
result = [];
for m_col = m
result = horzcat(result, func(m_col));
end
Если func не возвращает вектор-столбец, вы можете добавить что-то вроде
f = func(m_col);
result = horzcat(result, f(:));
чтобы заставить его в колонну.
Код OP заранее выделяет матрицу result, этот код - нет. Вместо этого он увеличивает матрицу на каждой итерации, что влечет за собой большие штрафы. Всегда нужно пытаться использовать массивы предварительно выделить в MATLAB.
Ваше решение в порядке.
Обратите внимание, что Horizcat значительно снижает производительность для больших матриц. Это делает код O (N ^ 2) вместо O (N). Для матрицы 100х10 000 ваша реализация на моей машине занимает 2,6 секунды, а для матрицы Horizcat - 64,5 секунды. Для матрицы 100x5000 реализация горизонтальной развертки занимает 15,7 с.
При желании вы можете немного обобщить свою функцию и сделать так, чтобы она могла перебираться по окончательному измерению или даже по произвольным измерениям (а не только по столбцам).
Не забудьте предварительно выделить матрицу результатов, если вы имеете дело с большими матрицами. В противном случае ваш процессор будет тратить много циклов, повторно перераспределяя матрицу каждый раз, когда он добавляет новую строку / столбец.
Способ вызвать неявный цикл по столбцам матрицы - использовать cellfun. То есть вы должны сначала преобразовать матрицу в массив ячеек, каждая ячейка будет содержать один столбец. Тогда позвони в Cellfun. Например:
A = randn(10,5);
Обратите внимание: здесь я вычислил стандартное отклонение для каждого столбца.
cellfun(@std,mat2cell(A,size(A,1),ones(1,size(A,2))))
ans =
0.78681 1.1473 0.89789 0.66635 1.3482
Конечно, многие функции в MATLAB уже настроены для работы со строками или столбцами массива, как указывает пользователь. Это, конечно, верно для std, но это удобный способ проверить, успешно ли работает cellfun.
std(A,[],1)
ans =
0.78681 1.1473 0.89789 0.66635 1.3482
Это подходящее решение, просто требуется дополнительная память. Чтобы соответствовать использованию OP, добавьте 'UniformOutput',false к вызову cellfun, затем объедините все (надеюсь) векторы столбцов, которые создаются, обратно в матрицу с использованием horzcat(result{:}) или эквивалентного cat(2,result{:}). Это решение примерно так же эффективно, как и код в OP, поскольку cellfun реализован с использованием цикла очень похожим образом.
Это не работает для функции сглаживания. Если вы передадите матрицу сглаживания, она будет рассматривать ее как один большой вектор. Однако этот метод был бы удобен для некоторых других функций.