2014-09-11 6 views
1

Matlab에서 행렬에 대한 논리 인덱스를 만들 때 상대 위치를 유지하기 위해 NaN (또는?) 행렬을 초기화해야하는 것처럼 보입니다. 예를 들어, 다음 예제를 고려하십시오매트릭스 리턴 벡터의 논리적 인덱싱 - 초기화 필요?

위의 코드에 명시된 바와 같이
clear all; close all; clc; 

Data = [1 2 3 4; 3 40 5 6; 5 6 7 8]; 
ind = logical([0 0 0 0;0 1 1 0;0 1 0 0]); 

tic 
x1 = NaN * ones(3,4); 
y1 = NaN * ones(1,4); y2 = y1; 
x1(ind) = Data(ind); % writing to pre-allocated NaN matrix (necessary?) 
y1(1:4) = nanmean(x1,1); % take NaN-mean - good result 
toc 

% Can we get rid of x1? The following obviously does not work: 
y2(1:4) = nanmean(Data(ind),1); 

, Data(ind)은 원래 크기를 유지하지, 벡터를 반환합니다. 지금까지 가지고있는 유일한 해결책은 올바른 크기로 초기화 된 x1을 사용하는 것입니다. 그래서 : 전체 (x1) NaN 행렬이 필요합니까? 이것이 어떻게 피할 수 있는지에 대한 아이디어가 있습니까? 이 코드의 속도를 높이려고 노력하면서 for 루프를 찾고 있지 않습니다.

+1

'Data'가, 수 있도록 우리가 출력으로 이어질? – Divakar

+0

여러 개의 다른 선택 항목에 대해 '데이터'를 사용할 수 있습니다. 그래서 덮어 쓰지 않으면 나는 그것을 선호한다. –

답변

1

accumarray을 사용하면 여기에서 구할 수 있지만 출력물을 미리 할당해야합니다. 그래도 출력물을 사용하면 좋겠지 만 처음부터 필요하지는 않습니다. . 문제의 경우 여기에 두 개의 appproach를 사용할 수 있습니다.

접근 # 1

[~,c] = find(ind); %// get column indices 
out = NaN(1,size(Data,2)); %// pre-allocate for output 

calc_result = accumarray(c,Data(ind),[], @mean) %// get mean calculated results 
array1 = 1:max(c) 
vind = ismember(array1,c) %// valid indices 
out(array1(vind)) = calc_result(vind) 

접근 # 2

[~,c] = find(ind); %// get column indices OR try c = ceil(find(ind)/size(ind,1)) 
vind = c(diff([0 ; c])~=0); %// valid indices 

out(1,1:size(Data,2)) = NaN; %// pre-allocate for output 
calc_result = accumarray(c,Data(ind),[], @mean); %// get mean calculated results 
out(vind) = calc_result(vind); 

접근 번호와 신뢰할 수있는 출력 y1와 비교

전체 코드 1 -

clear all; close all; clc; 

% Initialization 
x1 = NaN * ones(3,4); 
y1 = NaN * ones(1,4); 
y2 = y1; 

Data = [ 
    1 2 3 4; 
    3 4 5 6; 
    5 6 7 8] 

% Indices of data to be averaged over rows: 
ind = logical([0 0 0 0;0 1 0 0;0 1 0 1]) 

x1(ind) = Data(ind); % writing to pre-allocated NaN matrix (necessary?) 
y1(1:4) = nanmean(x1,1) % take NaN-mean - good result 

[~,c] = find(ind); %// get column indices 
out = NaN(1,size(Data,2)); %// pre-allocate for output 

calc_result = accumarray(c,Data(ind),[], @mean); 
array1 = 1:max(c); 
vind = ismember(array1,c); 
out(array1(vind)) = calc_result(vind) 

출력 -

우리가 변경할 수
Data = 
    1  2  3  4 
    3  4  5  6 
    5  6  7  8 
ind = 
    0  0  0  0 
    0  1  0  0 
    0  1  0  1 
y1 = 
    NaN  5 NaN  8 
out = 
    NaN  5 NaN  8 
+0

네 말이 맞아. 전반적으로, 코드는 평균이 계산되는'accumarray' 행에 1.5 초를 보낸다. 요소의 수를 가진'accumarray' 행은 0.5 초가 걸리고,'sum (ind (:, 1 : numel))'은 0.2 초가 걸립니다. 그래서 진실로 거기 개선. 출력 변수를 할당하는 행은 0.25 초 밖에 걸리지 않습니다. –

+1

시간과 노력에 감사드립니다. 많은 감사를드립니다. 타이밍 정보가 정확하지 않아서 다른 독자에게 부적절하거나 혼란 스럽기 때문에 이전 의견을 삭제했습니다. 귀하의 솔루션, 특히 # 2는 매력처럼 작동합니다. –

0

답 : 예, 전체 매트릭스의 경우 정확한 매트릭스 크기와 모양을 얻으려면 사전 초기화가 필요합니다.

메모리 낭비가 염려되는 경우 sparse 명령을 사용하여 스파 스 매트릭스를 생성 할 수 있습니다. 이 경우 논리 인덱스를 별도의 행 및 열 인덱스로 분해해야합니다.

+0

빠른 응답을 보내 주셔서 감사합니다. 딜란. 나는 그런 식으로 생각하지는 않았지만 다소 기억에 관심이있다. 본질적으로 할당 및 작업은 내가 줄이려는 훨씬 더 큰 분석에서 시간을 필요로합니다. 드문 드문 드문 일이긴하지만 논리적 인 것에서 인덱스로 변환하는 것이 더 많은 계산 시간을 필요로한다고 생각되기 때문에 상상할 수 있습니다. 또한 스파 스 매트릭스는 실제로 더 클 수도 있고 (http://www.mathworks.com/matlabcentral/answers/126295-memory-usage-in-sparse-matrix 참조) 또한 다른 요소에 대해 잘못 가정 할 수도 있습니다. –

+1

매트릭스의 메모리는 어느 시점에서 할당되어야합니다. 스파 스 또는 전체 매트릭스의 두 가지 옵션이 있습니다. 전체 매트릭스를 선택하면 해당 메모리가 할당 될 때와 동일한 양의 메모리 (및 동일한 할당 시간)가 필요합니다. –

+0

그러나 최종 목표가'나노 만 '을하는 것이라는 사실을 몰랐습니다.'누적 배열'을 사용하는 것은 확실히 좋은 해결책입니다. –