Вы можете применить функцию к каждому элементу в векторе, указав, например, v + 1
, или вы можете использовать функцию arrayfun
. Как я могу сделать это для каждой строки/столбца матрицы без использования цикла for?Как я могу применить функцию к каждой строке/столбцу матрицы в MATLAB?
ответ
Многие встроенные операции, такие как sum
и prod
, уже могут работать через строки или столбцы, поэтому вы можете реорганизовать функцию, которую вы применяете, чтобы воспользоваться этим.
Если это не является жизнеспособным вариантом, один из способов сделать это, чтобы собрать строки или столбцы в клетки с помощью mat2cell
или num2cell
, а затем использовать cellfun
работать на результирующем массиве ячеек.
В качестве примера предположим, что вы хотите суммировать столбцы матрицы M
. Вы можете сделать это просто с помощью sum
:
M = magic(10); %# A 10-by-10 matrix
columnSums = sum(M, 1); %# A 1-by-10 vector of sums for each column
А вот как вы могли бы сделать это, используя более сложный num2cell
/cellfun
вариант:
M = magic(10); %# A 10-by-10 matrix
C = num2cell(M, 1); %# Collect the columns into cells
columnSums = cellfun(@sum, C); %# A 1-by-10 vector of sums for each cell
Наткнулся на этот вопрос/ответ, ища, как вычислить суммы строк матрицы.
Я хотел бы добавить, что функция SUM Matlab имеет поддержку суммирования для заданной размерности, то есть стандартной матрицы с двумя измерениями.
Таким образом, чтобы вычислить суммы столбцов сделать:
colsum = sum(M) % or sum(M, 1)
и для строчных сумм, просто сделать
rowsum = sum(M, 2)
Моя ставка является то, что это быстрее, чем как программирование для цикла и преобразования в cells :)
Все это можно найти в справочной системе Matlab для SUM.
Возможность применения SUM по заданному измерению была упомянута в первом предложении исходного ответа на этот вопрос. Затем в ответ был рассмотрен случай, когда возможность выбора измерения еще не встроена в функцию. Вы правы, однако, что использование встроенных параметров выбора размеров - когда они доступны - почти всегда быстрее, чем цикл for или преобразование в ячейки. – cjh
Правда, однако, вышеприведенный ответ отправил меня обратно в документацию matlab, так как мне не нужна вся эта фантазия, поэтому я просто хотел поделиться и спасти других, нуждающихся в простом решении, от поиска. – nover
Я не могу комментировать, насколько эффективно это, но вот решение:
applyToGivenRow = @(func, matrix) @(row) func(matrix(row, :))
applyToRows = @(func, matrix) arrayfun(applyToGivenRow(func, matrix), 1:size(matrix,1))'
% Example
myMx = [1 2 3; 4 5 6; 7 8 9];
myFunc = @sum;
applyToRows(myFunc, myMx)
Дается более общий ответ [здесь] (http://stackoverflow.com/a/15971182/376454). – Wok
Опираясь на Alex's answer, здесь более общая функция:
applyToGivenRow = @(func, matrix) @(row) func(matrix(row, :));
newApplyToRows = @(func, matrix) arrayfun(applyToGivenRow(func, matrix), 1:size(matrix,1), 'UniformOutput', false)';
takeAll = @(x) reshape([x{:}], size(x{1},2), size(x,1))';
genericApplyToRows = @(func, matrix) takeAll(newApplyToRows(func, matrix));
Вот сравнение две функции:
>> % Example
myMx = [1 2 3; 4 5 6; 7 8 9];
myFunc = @(x) [mean(x), std(x), sum(x), length(x)];
>> genericApplyToRows(myFunc, myMx)
ans =
2 1 6 3
5 1 15 3
8 1 24 3
>> applyToRows(myFunc, myMx)
??? Error using ==> arrayfun
Non-scalar in Uniform output, at index 1, output 1.
Set 'UniformOutput' to false.
Error in ==> @(func,matrix)arrayfun(applyToGivenRow(func,matrix),1:size(matrix,1))'
Возможно, вам понадобится более неясная функция Matlab bsxfun. В документации Matlab bsxfun «применяет двоичную операцию« по одному элементу », указанную функцией fun fun в массивах A и B, с включенным расширением singleton».
@gnovice, указанный выше, что сумма и другие базовые функции уже действуют на первое измерение не одиночного элемента (т. Е. Строки, если имеется более одной строки, столбцы, если есть только одна строка или более высокие размеры, если все нижние размеры имеют размер == 1). Тем не менее, bsxfun работает для любой функции, включая (и особенно) пользовательские функции.
Например, предположим, что у вас есть матрица A и вектор-строку BEG, скажем:
A = [1 2 3;
4 5 6;
7 8 9]
B = [0 1 2]
Вы хотите функцию power_by_col, которая возвращает в вектор C все элементы А к власти соответствующий столбец B.
из приведенного выше примера, с представляет собой матрицу 3х3:
C = [1^0 2^1 3^2;
4^0 5^1 6^2;
7^0 8^1 9^2]
т.е.
C = [1 2 9;
1 5 36;
1 8 81]
Вы могли бы сделать это грубая сила способ с использованием repmat:
C = A.^repmat(B, size(A, 1), 1)
Или вы могли бы сделать это классный способ использования bsxfun, который внутренне ухаживает за шагом repmat:
C = bsxfun(@(x,y) x.^y, A, B)
Таким образом, bsxfun сохраняет некоторые шаги (вам не нужно явно вычислять размеры A). Однако в некоторых неофициальных моих тестах получается, что repmat примерно в два раза быстрее, если функция, которая будет применяться (например, моя функция мощности выше) проста. Поэтому вам нужно будет выбрать, хотите ли вы простоты или скорости.
Принимаемый ответ, похоже, состоит в том, чтобы сначала преобразовать в ячейки, а затем использовать cellfun
для управления всеми ячейками. Я не знаю конкретного приложения, но в целом я бы подумал, что использование функции bsxfun
для работы над матрицей будет более эффективным. В основном bsxfun
применяет операцию поэтапно по двум массивам. Так что если вы хотите, чтобы умножить каждый элемент в n x 1
вектора каждого элемента в m x 1
вектора, чтобы получить n x m
массив, вы можете использовать:
vec1 = [ stuff ]; % n x 1 vector
vec2 = [ stuff ]; $ m x 1 vector
result = bsxfun('times', vec1.', vec2);
Это даст вам матрица называется result
где (I, J) запись будет i-м элементом vec1
, умноженным на j-й элемент vec2
.
Вы можете использовать bsxfun
для всех видов встроенных функций, и вы можете объявить о себе. В документации есть список многих встроенных функций, но в основном вы можете назвать любую функцию, которая принимает в качестве аргументов два массива (вектор или матрицу) и заставить их работать.
если вы знаете длину ваших строк вы можете сделать что-то вроде этого:
a=rand(9,3);
b=rand(9,3);
arrayfun(@(x1,x2,y1,y2,z1,z2) line([x1,x2],[y1,y2],[z1,z2]) , a(:,1),b(:,1),a(:,2),b(:,2),a(:,3),b(:,3))
Тем, кто видит этот ответ: Это не способ сделать это! Это не способ сделать что-либо в MATLAB! –
Для полноты/интерес, я хотел бы добавить, что MATLAB действительно имеет функцию, которая позволяет работать на данных в но не для каждого элемента. Он называется rowfun
(http://www.mathworks.se/help/matlab/ref/rowfun.html), но единственная «проблема» в том, что он работает на таблицах (http://www.mathworks.se/help/matlab/ref/table.html), а не . Матрицы.
С последними версиями Matlab вы можете использовать структуру данных Table в своих интересах.Там даже «rowfun» операция, но я нашел, что это легче всего сделать это:
a = magic(6);
incrementRow = cell2mat(cellfun(@(x) x+1,table2cell(table(a)),'UniformOutput',0))
или вот старший один я, что не требует таблиц, для более старых версий Matlab.
dataBinner = cell2mat(arrayfun(@(x) Binner(a(x,:),2)',1:size(a,1),'UniformOutput',0)')
Добавление к меняющемуся характеру ответа на этот вопрос, начиная с r2016b, MATLAB будет неявно расширить одноэлементные размеры, устраняя необходимость в bsxfun
во многих случаях.
Неявного Расширение: Применение поэлементны операциями и функций в массивах с автоматическим расширением размеров длиной 1
Неявные разложением является обобщением скалярного расширения. С скалярным расширением скаляр расширяется до того же размера, что и другой массив , чтобы облегчить элементарные операции. При неявном расширении перечисленные здесь элементарные функции и функции могут неявно расширять свои входы до того же размера, если массивы имеют совместимых размеров. Два массива имеют совместимые размеры, если для каждого измерения размеры размеров входов либо одинаковы, либо , один из которых равен 1. См. Раздел Совместимые размеры массивов для основных операций и Операции с массивом и матрицей для получения дополнительной информации.
Element-wise arithmetic operators — +, -, .*, .^, ./, .\ Relational operators — <, <=, >, >=, ==, ~= Logical operators — &, |, xor Bit-wise functions — bitand, bitor, bitxor Elementary math functions — max, min, mod, rem, hypot, atan2, atan2d
Например, можно вычислить среднее значение каждого столбца в матрице А, , а затем вычесть вектор средних значений из каждой колонки с А - среднего (А).
Ранее эта функция была доступна через функцию bsxfun. Теперь рекомендуется заменить большинство применений bsxfun на прямые вызовы вызовам функций и операторов, которые поддерживают неявное расширение. По сравнению с использованием bsxfun неявное расширение предлагает более быструю скорость, лучшее использование памяти и улучшенную читаемость кода.
Ни один из вышеперечисленных ответов не работает «из коробки» для меня, однако, следующая функция, полученная путем копирования идей других ответов работы:
apply_func_2_cols = @(f,M) cell2mat(cellfun(f,num2cell(M,1), 'UniformOutput',0));
Он принимает функцию f
и применяет его к каждому столбцу матрицы M
.
Так, например:
f = @(v) [0 1;1 0]*v + [0 0.1]';
apply_func_2_cols(f,[0 0 1 1;0 1 0 1])
ans =
0.00000 1.00000 0.00000 1.00000
0.10000 0.10000 1.10000 1.10000
Я бы проверить эффективность такого подхода для каждого конкретного случая с простым для цикла, что может быть быстрее, чем преобразование матрицы в ячейку массива. Используйте tic/tac wrap для тестирования. – yuk
@yuk: Я думаю, вы имели в виду «тик/ток». ;) – gnovice
Упс, конечно! Просто что-то тикает ... :) – yuk