2013-12-16 3 views
8

sh의 크기가 cs 인 겹치는 서브 벡터로 나눠 넣으려는 벡터가 있습니다. 상상 입력 벡터는 다음과 같습니다 입력 벡터가 반드시 아니라고matlab : 벡터를 고정 크기의 겹치는 덩어리로 나눕니다.

[1 2 3 4] 
[3 4 5 6] 
[5 6 7 8] 
[7 8 9 10] 
[9 10 11 12] 

참고 :

v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13] 

chunksize 2 (sh=2)의 4 (cs=4)과 변화에 대해서, 그 결과는 같아야합니다 chunksize으로 나눌 수 있으므로 일부 서브 벡터는 버려집니다. 예를 들어를 사용하지 않고도이를 계산할 수있는 빠른 방법이 있습니까? for 루프? 관련된 post에서 나는 겹치지 않는 서브 벡터를 고려할 때 그것을 어떻게하는지 발견했습니다.

답변

0

어떨까요? 먼저 cssh을 기반으로 시작 인덱스를 생성하여 전체 길이 벡터에서 단일 벡터를 조각화 한 다음 idx+cs이 벡터 길이를 초과 할 모든 인덱스를 삭제 한 다음 단일 하위 벡터를 잘라냅니다

v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13] 
cs=4; 
sh=2; 

idx = 1:(cs-sh):length(v); 
idx = idx(idx+cs-1 <= length(v)) 
A = arrayfun(@(i) v(i:(i+cs-1)), idx, 'UniformOutput', false); 
cell2mat(A') 

예 : arrayfun 그리고 이후는 매트릭스로 변환 경유 cs=5; sh=3;이 줄 것이다 :

idx = 

    1  3  5  7 


ans = 

    1  2  3  4  5 
    3  4  5  6  7 
    5  6  7  8  9 
    7  8  9 10 11 

이 값에서 온 cs; sh 위치에 따라, 당신은 아마 sh < cscs > 0; 있도록뿐만 아니라 간단한 오류 점검을 소개 할 것입니다. sh < 0은 이론적으로 몇 가지 값을 남기고 싶다면 가능할 것입니다.

EDIT : 매우 작은 버그가 수정되었으며 sh와 cs의 다른 조합에 대해 실행 중이어야합니다.

+0

왜해야합니까? 그것은 다른 숫자로 잘 작동합니다. 'idx'는 나에게 서브 벡터의 시작 인덱스를 제공하기로되어 있기 때문에, 나는 def를 사용한다. 단계로 cs-sh가 필요합니다. 편집 : 다른 벡터와 다른 수의'cs'와'sh '를 사용하여 시도해 보았습니다. 꽤 잘 작동합니다. – tim

+0

'cs = 5; sh = 3' 나는 시작 인덱스를 '1 3 5 7'이 아니라'1 4 7 '이라고 가정합니다. 이 경우'idx = 1 : sh : length (v)'를 사용합니다. –

+1

미안하지만 나는 당신에게 말해야한다, 그것은 틀렸다. 그것에 대해 다시 생각해보십시오. '1 3 5 7'은 올바른 인덱스입니다 - 분명히 올바른 (제 5 열 (5 열)) 명확하게 볼 수 있듯이 내 출력 행렬을보십시오 (이것은 chunksize cs = 5 임) 및 3 개의 중복 항목 각 행의 마지막 세 항목은 다음 행의 세 번째 첫 항목입니다.) – tim

2

가장 간단한 방법은 실제로 루프를 사용하는 것입니다. 벡터화 솔루션은 더 빨라질 수 있지만 결과가 적절히 사전 할당 된 경우 루프가 잘 수행되어야합니다.

v = 1:13 
cs = 4; 
sh = 2; 

myMat = NaN(floor((numel(v) - cs)/sh) + 1,cs); 
count = 0; 

for t = cs:sh:numel(v) 
    count = count+1; 
    myMat(count,:) = v(t-cs+1:t); 
end 
+1

Tin이 'for'-loop가없는 해결책을 요구하면서 특히 이것이 필요한 이유는 알 수 없습니다. – tim

+1

@bjoern : Dennis와 동의합니다. 그의 솔루션은 단순합니다. Arrayfun은 기본적으로 for 루프이며,이 경우 훨씬 더 느립니다. – thewaywewalk

+0

@bjoern arrayfun은 루프에 대한 래퍼 일 뿐이므로 (따라서 간단한 루프보다 성능이 우수하지는 않음) 유의하십시오. –

5

다음과 같은 방식으로 기능 bsxfun를 사용할 수 있습니다 어떻게 작동하는지

다음
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13] 
cs=4; 
sh=2; 

A = v(bsxfun(@plus,(1:cs),(0:sh:length(v)-cs)')); 

입니다. bsxfun은 2 개의 배열에 몇 가지 기본 기능을 적용하고 입력 크기가 맞지 않으면 일부를 수행합니다 (repmat). 이 경우 첫 번째 청크의 색인을 생성하고 각 청크의 오프셋을 추가합니다. 한 입력이 행 벡터이고 다른 입력이 열 벡터이므로 결과는 행렬입니다. 마지막으로, 행렬을 사용하여 벡터를 인덱싱 할 때 결과는 행렬입니다. 정확히 예상 한 것입니다.

그리고 그것은 거의 하나의 라이너입니다. (거의 항상) 재미 있습니다.

+0

'cs = 5; sh = 2;'로 시도해보십시오. 3과 2는 중복되지 않을 것입니다 (두 개는 sh = 2로 맞을 것입니다). – tim

+0

@bjoern 질문에 대한 언급에서 언급했듯이, 당신의 솔루션은 실제로 다른 결과를 준다. 그러나 이것이 꼭 필요한 것은 아닙니다. –

+0

좋아요, 이제 당신이 추천하는 것을 보았습니다. 나는 sh가 중복 된 항목의 수를 기술했는지 100 % 확신했지만, 이제는 당신이 그것을 다른 척도로 참조하고있는 것을 볼 수 있습니다. 죄송합니다. 내 잘못은 정말 그 Oo를 놓쳐 버렸음에 틀림 없습니다. 게시 된 예제가 모호하므로 설명이 고유하지 않습니다. – tim

1

신호 처리 도구 상자가 있습니까? 그런 다음 명령은 buffer입니다.베어 출력에서 ​​첫 모습 : 말했다

[y z] = buffer(v, 4, 2, 'nodelay'); 
y.' 

ans = 
    1  2  3  4 
    3  4  5  6 
    5  6  7  8 
    7  8  9 10 
    9 10 11 12 

는 벡터 칼럼 떠나 고려해 필요한 경우에만 약간의 조정과 함께, 분명 올바른 생각

buffer(v, 4, 2) 

ans = 
    0  1  3  5  7  9 11 
    0  2  4  6  8 10 12 
    1  3  5  7  9 11 13 
    2  4  6  8 10 12  0 

당신이 원하는 당신에게 정확하게 출력을 제공합니다 대부분의 유스 케이스에 더 잘 맞습니다. 예를 들어 각 창의 평균은 행렬의 기본값 인 행렬의 mean입니다.

+0

나는 도구 상자에 이미있는 것을 알지 못했던이 작은 보석들을 사용하는 것을 좋아합니다. 문제는 마지막 프레임에서 부분 데이터로 남겨 둘 수 있지만 달성하려는 결과에 달려 있다는 것입니다. –

1

당신은 ndgrid으로이 작업을 수행 할 수 있습니다

second syntax of the colon operator ( j:i:k)의 좋은 점은 당신이를 폐기하려는 경우 (예 : 1:2:6[1 3 5]을 제공합니다) 정확히 k을 계산하지 않아도됩니다
>> v=1:13; cs=4; sh=2; 
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1) 
>> chunks = X+Y 
chunks = 
    1  2  3  4 
    3  4  5  6 
    5  6  7  8 
    7  8  9 10 
    9 10 11 12 

이 문제와 같이 추가 항목. 자동으로 j+m*i으로 이동합니다. 여기서 m = fix((k-j)/i);

다른 시험 :

>> v=1:14; cs=5; sh=2; % or v=1:15 or v=1:16 
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1); chunks = X+Y 
chunks = 
    1  2  3  4  5 
    4  5  6  7  8 
    7  8  9 10 11 
    10 11 12 13 14 

그리고 새로운 행은 v=1:17으로 형성됩니다. 필요에 따라 모든 사례를 처리합니까?