Как лучше всего перебирать столбцы матрицы?

Я хочу применить функцию ко всем столбцам в матрице с помощью 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)));

Что-то не так с этим кодом? Как я мог это улучшить?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
11
0
17 958
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

Это не совсем решит вашу проблему, но упростит использование функций. В этом случае на выходе тоже должна быть матрица.

Вы также можете преобразовать матрицу в один длинный столбец с помощью m(:,:) = m(:). Однако это зависит от вашей функции, если это будет иметь смысл.

Возможно, вы всегда можете преобразовать матрицу с помощью оператора ', а затем преобразовать результат обратно.

smoothed = smooth(input', 9)';

По крайней мере, это работает с функцией fft.

Это не работает для функции сглаживания. Если вы передадите матрицу сглаживания, она будет рассматривать ее как один большой вектор. Однако этот метод был бы удобен для некоторых других функций.

dmnd 21.10.2008 10:18
' - это транспонированный комплексный конъюгат. Если цель состоит в том, чтобы поменять местами два измерения матрицы, используйте .'.
Cris Luengo 15.12.2018 08:00

Оператор 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.

Cris Luengo 15.12.2018 08:00
Ответ принят как подходящий

Ваше решение в порядке.

Обратите внимание, что 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 реализован с использованием цикла очень похожим образом.

Cris Luengo 15.12.2018 08:17

Другие вопросы по теме