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

StackOverflow https://stackoverflow.com/questions/216341

  •  03-07-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

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

Обратите внимание, что horizcat требует значительного снижения производительности для больших матриц. Это делает код O (N ^ 2) вместо O (N). Для матрицы 100x10 000 ваша реализация занимает 2,6 с на моей машине, горизонтальная - 64,5 с. Для матрицы 100x5000 реализация horizcat занимает 15,7 с.

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

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

MATLAB " для " На самом деле оператор зацикливается на столбцах того, что было предоставлено - обычно это просто приводит к последовательности скаляров, поскольку вектор, переданный в 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(:));

чтобы заставить его в столбец.

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

smoothed = smooth(input', 9)';

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

Способ вызвать неявный цикл по столбцам матрицы - использовать 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

Не забудьте предварительно выделить матрицу результатов, если вы имеете дело с большими матрицами. В противном случае ваш ЦП будет тратить много циклов, многократно перераспределяя матрицу при каждом добавлении новой строки / столбца.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top