태그 보관물: matrix

matrix

MATLAB에서 행렬의 모든 행 / 열에 함수를 적용하려면 어떻게해야합니까? 항목에 함수를 적용하거나

예를 들어라고 말하여 벡터의 모든 항목에 함수를 적용하거나 함수를 v + 1사용할 수 있습니다 arrayfun. for 루프를 사용하지 않고 행렬의 모든 행 / 열에 대해 어떻게 할 수 있습니까?



답변

많은 같은 작업을 내장 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


답변

좀 더 모호한 Matlab 함수 bsxfun을 원할 수 있습니다 . Matlab 문서에서 bsxfun은 “함수 핸들 fun에 의해 지정된 요소 별 이진 연산을 단일 확장이 활성화 된 배열 A와 B에 적용합니다.”

@gnovice는 sum 및 기타 기본 함수가 이미 첫 번째 비단 일 차원 (즉, 행이 둘 이상인 경우 행, 행이 하나만있는 경우 열, 더 낮은 차원이 모두 size == 1 인 경우 더 높은 차원)에서 이미 작동한다고 명시했습니다. ). 그러나 bsxfun은 (특히) 사용자 정의 함수를 포함한 모든 함수에서 작동합니다.

예를 들어 행렬 A와 행 벡터 BEg가 있다고 가정 해 보겠습니다.

A = [1 2 3;
     4 5 6;
     7 8 9]
B = [0 1 2]

A의 모든 요소를 ​​B의 해당 열의 거듭 제곱으로 벡터 C에서 반환하는 함수 power_by_col을 원합니다.

위의 예에서 C는 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)

또는 내부적으로 repmat 단계를 처리하는 bsxfun을 사용하여 고급 방식으로 수행 할 수 있습니다.

C = bsxfun(@(x,y) x.^y, A, B)

따라서 bsxfun은 몇 가지 단계를 절약합니다 (A의 차원을 명시 적으로 계산할 필요가 없음). 그러나 내 일부 비공식 테스트에서 적용 할 기능 (위의 내 힘 기능과 같이)이 간단하다면 repmat이 대략 두 배 빠른 것으로 나타났습니다. 따라서 단순성 또는 속도를 원하는지 선택해야합니다.


답변

이것이 얼마나 효율적인지에 대해서는 언급 할 수 없지만 여기에 해결책이 있습니다.

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)


답변

바탕 알렉스의 대답은 여기에서 더 일반적인 기능은 다음과 같습니다

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에는 요소 당이 아닌 행당 데이터를 처리 할 수있는 기능이 있다는 점을 추가하고 싶습니다. rowfun( http://www.mathworks.se/help/matlab/ref/rowfun.html ) 이라고 하지만 유일한 “문제”는 테이블에서 작동한다는 것입니다 ( http://www.mathworks.se/help/ matlab / ref / table.html ) 대신 matrices .


답변

r2016b부터 시작하여이 질문에 대한 답변의 진화하는 특성에 추가하여 MATLAB은 암시 적으로 단일 차원을 확장 bsxfun하여 많은 경우에 대한 필요성을 제거합니다 .

로부터 r2016b 릴리스 정보 :

암시 적 확장 : 길이 1의 차원을 자동으로 확장하여 배열에 요소 별 연산 및 함수 적용

암시 적 확장은 스칼라 확장의 일반화입니다. 스칼라 확장을 사용하면 스칼라가 다른 배열과 동일한 크기로 확장되어 요소 별 연산을 용이하게합니다. 암시 적 확장을 사용하면 여기에 나열된 요소 별 연산자 및 함수는 배열의 크기가 호환되는 한 암시 적으로 입력을 동일한 크기로 확장 할 수 있습니다. 모든 차원에 대해 입력의 차원 크기가 같거나 그 중 하나가 1 인 경우 두 배열의 크기가 호환됩니다. 자세한 내용은 기본 연산 및 배열 대 행렬 연산을위한 호환 가능한 배열 크기를 참조하세요.

Element-wise arithmetic operators+, -, .*, .^, ./, .\

Relational operators<, <=, >, >=, ==, ~=

Logical operators&, |, xor

Bit-wise functionsbitand, bitor, bitxor

Elementary math functionsmax, min, mod, rem, hypot, atan2, atan2d

예를 들어 행렬 A에서 각 열의 평균을 계산 한 다음 A-mean (A)을 사용하여 각 열에서 평균 값 벡터를 뺄 수 있습니다.

이전에는이 ​​기능을 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