예를 들어라고 말하여 벡터의 모든 항목에 함수를 적용하거나 함수를 v + 1
사용할 수 있습니다 arrayfun
. for 루프를 사용하지 않고 행렬의 모든 행 / 열에 대해 어떻게 할 수 있습니까?
예를 들어라고 말하여 벡터의 모든 항목에 함수를 적용하거나 함수를 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
true = false
유효한 진술이 있는 언어에서 , 당신이 그것을 할 수있는 방법이 있다고 확신합니다 (:
sum(M, 1)
. 초보자는 sum
임의의 크기의 행렬에 대해 이런 식으로 사용할 수 있다고 생각한 다음 행렬이 1-by-n
.
좀 더 모호한 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는 3x3 행렬입니다.
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 functions — bitand, bitor, bitxor Elementary math functions — max, 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
최신 버전의 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)')
허용되는 대답은 먼저 셀로 변환 한 다음 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
기능에 내장 된 모든 종류의, 당신은 당신의 자신을 선언 할 수 있습니다. 문서에는 많은 내장 함수 목록이 있지만 기본적으로 두 배열 (벡터 또는 행렬)을 인수로 받아들이는 함수의 이름을 지정하고 작동하도록 할 수 있습니다.
행렬의 행 합계를 계산하는 방법을 찾는 동안이 질문 / 답변을 우연히 발견했습니다.
Matlab의 SUM 함수가 실제로 주어진 차원, 즉 2 차원이있는 표준 행렬에 대한 합계를 지원한다는 것을 추가하고 싶습니다.
따라서 열 합계를 계산하려면 다음을 수행하십시오.
colsum = sum(M) % or sum(M, 1)
행 합계의 경우 간단히
rowsum = sum(M, 2)
내 생각은 이것이 for 루프를 프로그래밍하고 셀로 변환하는 것보다 빠르다는 것입니다. :)
이 모든 것은 SUM에 대한 MATLAB 도움말에서 찾을 수 있습니다.
행의 길이를 알고 있다면 다음과 같이 만들 수 있습니다.
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) )