how to fill a column with 1's between two specific values and with 0 otherwise?

7 ビュー (過去 30 日間)
James Grayot
James Grayot 2016 年 7 月 3 日
編集済み: Andrei Bobrov 2016 年 7 月 3 日
Dear all
I have a matrix with 27 columns. The rows are time periods. Each column takes value 1, 0 or -1. For instance, a typical column would look like this:
%
0
0
1
0
0
0
-1
0
0
1
0
0
0
0
-1
0
0
1
end
If you imagine a time series, values of 1 mean a peak, values of -1 mean a trough. Hence, we can define a period of expansion as the period between any t=1 and t=-1 (including these two endpoints).
I want to create a matrix such that each column has 1's in every period belonging to an expansion period and 0's otherwise. For instance, the column above would become
%
0
0
1
1
1
1
1
0
0
1
1
1
1
1
1
0
0
0
end
My question is how to this in an efficient manner and in a way that applies to every column of the matrix at once. I struggling with the end values. For instance, the last value is a 1 but since there is no -1 after it, it should become a 0!
Thanks for your help
James
Edit: Btw, this is what I have so far.... it has been running for quite a while so I have no idea whether it works or not.. but even if it does it really is inefficient
%
[R, C] = size(mBBpre); %mBBpre is the matrix of 0's,1's and -1's
mExpansionPre = NaN(R,C); %this is where I want to put the values
for j = 1 : C
% iLocalPeak is the number of Peaks for column j
iLocalPeak = vPeaksPre(j,1);
% iLocalTrough is the number of Troughs for column j
iLocalTrough = vTroughPre(j,1);
% Pre-allocates space
vPositionPeaksPre = NaN(iLocalPeak,1);
% Pre-allocates space
vPositionTroughPre = NaN(iLocalTrough,1);
% Stores Positions of Peaks
vPositionPeaksPre = find(mBBpre(:,j) == 1);
% Stores Positions of Troughs
vPositionTroughPre = find(mBBpre(:,j) == -1);
for k = 1 : numel(vPositionPeaksPre)
for i = 1 : numel(mExpansionPre)
if i >= vPositionPeaksPre(k,1) && i <= vPositionTroughPre(k,1)
mExpansionPre(i,j) = 1;
else
mExpansionPre(i,j) = 0;
end
end
end
end
end

採用された回答

dpb
dpb 2016 年 7 月 3 日
Sometimes it's just simpler to loop...
i1=find(v==1); % start
i2=find(v==-1); % end
if length(i2)>length(i1) % end effect, if any
v(i2(end))=0; % zero that position
ix(end)=[]; % and cleanup array length
end
for i=1:length(i1) % fill in the array locations wanted
v(i1(i):i2(i))=ones(i1(i)-i2(i)+1,1);
end
Some effort could turn this into an arrayfun candidate no doubt, but I suspect the above will be just as fast and easier to debug/maintain...
  6 件のコメント
dpb
dpb 2016 年 7 月 3 日
"does your code account for the possibility that you have this: peak - trough - peak - trough?"
No, of course not. That wasn't in the design spec, sorry. "SCOPE!" :)
If you've got a case that works, good, hopefully the posted code led you in the right direction but in future, realize we only know what we're told (while the crystal ball has been known to operate, it's a rare occurrence and more often it is in the shop for repair when needed than not) so if there are conditions such as these additional that are important, it's important those are given. Else't one receives a perfectly good solution, just wasn't the right question.
James Grayot
James Grayot 2016 年 7 月 3 日
True that, my apologies. I should have explained it more clearly. I did accept your answer btw. The "bright" side is that we ended up asnwering two different questions which may me useful in the future for others. Thank you for your help. :D

サインインしてコメントする。

その他の回答 (1 件)

Andrei Bobrov
Andrei Bobrov 2016 年 7 月 3 日
編集済み: Andrei Bobrov 2016 年 7 月 3 日
v = [0
0
1
0
0
0
-1
0
0
1
0
0
0
0
-1
0
0
1];
z = find(v == -1);
v(z) = 0;
v(z+1) = -1;
v(end) = 0;
out = cumsum(v);

カテゴリ

Help Center および File ExchangePulsed Waveforms についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by