Select nearest non zero value in column

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 comentarios

madhan ravi
madhan ravi el 1 de Nov. de 2018
example?
a = rand(11,4)
b = [0 0 0 2 0 0 0 0 0 3 0]'
c = [a b]
For the first six loops, the 2 should be used for the calculation and the last four loops, the 3 should be used for the calculations. It would be optimal if for the seventh loop, the average of 2 and 3 would be selected for the calculation, since it is has a similar distance to the two values.
Kevin Chng
Kevin Chng el 1 de Nov. de 2018
Can't get what you are saying.
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 el 1 de Nov. de 2018
Editada: Kevin Chng el 1 de Nov. de 2018
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

Iniciar sesión para comentar.

 Respuesta aceptada

Bruno Luong
Bruno Luong el 2 de Nov. de 2018
Editada: Bruno Luong el 2 de Nov. de 2018
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 comentarios

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 el 1 de Dic. de 2022
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!

Iniciar sesión para comentar.

Más respuestas (2)

the cyclist
the cyclist el 1 de Nov. de 2018
Editada: the cyclist el 1 de Nov. de 2018
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 comentarios

Guillaume
Guillaume el 1 de Nov. de 2018
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 el 1 de Nov. de 2018
I had the same thought. Hard to know, without more context from OP.

Iniciar sesión para comentar.

the cyclist
the cyclist el 1 de Nov. de 2018
Editada: the cyclist el 1 de Nov. de 2018
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);

Etiquetas

Preguntada:

el 1 de Nov. de 2018

Comentada:

el 1 de Dic. de 2022

Community Treasure Hunt

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

Start Hunting!

Translated by