Select nearest non zero value in column

조회 수: 12 (최근 30일)
Mabel Gray
Mabel Gray 2018년 11월 1일
댓글: michael fechter 2022년 12월 1일
Hi, I have a matrix of which the last column consists mainly of zeros and an occasionally non zero value. In a For loop I use each loop the next row for calculations, but for the last column I want to select the closest non zero value in that column. How should I do that? Thanks in advance!
  댓글 수: 5
the cyclist
the cyclist 2018년 11월 1일
Is it correct that given the input
b = [0 0 0 2 0 0 0 0 0 3 0]'
we could create the output
b2 = [2 2 2 2 2 2 2.5 3 3 3 3]'
then you would be all set?
Kevin Chng
Kevin Chng 2018년 11월 1일
편집: Kevin Chng 2018년 11월 1일
My solution is coming from hard code. I would like to see any other shorter solution.
b = [0 0 0 2 0 0 0 0 0 3 0]';
ind = find(b>0);
if numel(ind)>1
indaverage2(1) = 1;
for i=1:1:numel(ind)-1;
indaverage1(i+1) = (ind(i)+ind(i+1))/2;
indaverage2(i+1) = floor((ind(i)+ind(i+1))/2);
end
k=1;
indaverage2(end+1) = numel(b);
for i=1:1:numel(ind)
valueforcalculation(indaverage2(i):indaverage2(i+1)) = b(ind(i)) ;
end
for i=1:1:numel(indaverage1)-1
if floor(indaverage1(i+1))==indaverage1(i+1)
valueforcalculation(indaverage1(i+1)) = (b(ind(i))+b(ind(i+1)))/2;
end
end
elseif numel(ind)==1
valueforcalculation(1:numel(b)) = b(ind);
elseif numel(ind)==0
valueforcalculation(1:numel(b)) = 0;
end

댓글을 달려면 로그인하십시오.

채택된 답변

Bruno Luong
Bruno Luong 2018년 11월 2일
편집: Bruno Luong 2018년 11월 2일
b = [0; 0; 0; 2; 0; 0; 0; 0; 0; 3; 0]
nearestfun = @(b) interp1(find(b),b(b~=0),(1:length(b))','nearest','extrap');
closest = 0.5*(nearestfun(b) + flip(nearestfun(flip(b))))
  댓글 수: 2
Bruno Luong
Bruno Luong 2018년 11월 2일
A variant
b = [0; 0; 0; 2; 0; 0; 0; 0; 0; 3; 0]
nearestfun = @(b) interp1(find(b),b(b~=0),(1:length(b))','nearest','extrap');
closest = median([nearestfun(b),flip(nearestfun(flip(b)))],2)
michael fechter
michael fechter 2022년 12월 1일
Just had a similar problem of a frequency logger, skipping a few entries when an infinite value is recorded. works fine for what I was about to do hard coding.
Thanks!

댓글을 달려면 로그인하십시오.

추가 답변 (2개)

the cyclist
the cyclist 2018년 11월 1일
편집: the cyclist 2018년 11월 1일
Assuming my comment above is correct, then here is a somewhat ugly solution:
b = [0 0 0 2 0 0 0 0 0 3 0]';
nonZeroIdx = find(b);
b2 = interp1(nonZeroIdx,b(nonZeroIdx),1:numel(b),'nearest','extrap');
for ni = 1:numel(nonZeroIdx)-1
isOddIdx = mod(nonZeroIdx([ni ni+1]),2);
if not(xor(isOddIdx(1),isOddIdx(2)))
b2(round((nonZeroIdx(ni)+nonZeroIdx(ni+1))/2)) = (b(nonZeroIdx(ni))+b(nonZeroIdx(ni+1)))/2;
end
end
The first part is easy ... using nearest-neighbor interpolation will get most of the values correct.
But you need the for loop (I think) to get the elements that are halfway between non-zero values, and that is ugly. There might be a better way.
  댓글 수: 2
Guillaume
Guillaume 2018년 11월 1일
Wouldn't it make more sense to perform a linear interpolation and then round to the nearest 0.5? Granted you may get several consecutive values at 0.5 instead of just the middle one but wouldn't that be more appropriate?
the cyclist
the cyclist 2018년 11월 1일
I had the same thought. Hard to know, without more context from OP.

댓글을 달려면 로그인하십시오.


the cyclist
the cyclist 2018년 11월 1일
편집: the cyclist 2018년 11월 1일
Here is a slightly slicker way:
b = [0 0 0 2 0 0 0 0 0 3 0]';
nonZeroIdx = find(b);
b_extended = [b(nonZeroIdx(1)); b; b(nonZeroIdx(end))];
nonZeroIdx = [1; nonZeroIdx+1; numel(b_extended)];
b_lo = interp1(nonZeroIdx,b_extended(nonZeroIdx),1:numel(b_extended)-1,'nearest','extrap');
b_hi = interp1(nonZeroIdx,b_extended(nonZeroIdx),2:numel(b_extended), 'nearest','extrap');
out = (b_lo+b_hi)/2;
out = out(1:end-1);

카테고리

Help CenterFile Exchange에서 Special Characters에 대해 자세히 알아보기

태그

Community Treasure Hunt

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

Start Hunting!

Translated by