How to find the last nonzero element in an array where zeros are sprinkled throughout?
bendrinksalotofcoffee
Suppose I have a 1D wave that looks like:
{2,5,8,0,1,4,33,6,3,7,0,8,0,3,1,8,99,0,0,0,0,0,0,0,0}
I want to find the index of 99, which of course won't always be 99. It's just the last nonzero value before a trail of zeroes. I have hundreds of these waves and the last nonzero value is in a different place each time. The waves are also different lengths.
In Python, I would write
idx = numpy.max(numpy.nonzero(wave))
Or, without numpy:
idx = [index for index, item in enumerate(wave) if item != 0][-1]
But Igor doesn't have anything so elegant. Do I have to make a new reversed wave, then search element-by-element until I find something nonzero, then figure out what the non-reversed index is?
Hi,
One approach
replace 0 with nans, zapnans, read last value.
wave transform zapnans temp
lastvalue =temp[numpnts(temp)-1]
Alternative
loop from the end
for(i=numpnts(wave)-1;i<=0;i-=1)
if(!wave[i]
break
endif
endfor
then the value is wave[i] and the point where that occurs is i
Andy
September 30, 2024 at 09:23 am - Permalink
Hmm... somehow Andy's code is very broken today. Here is how this should look:
MatrixOp/Free temp=replace(input,0,Nan)
WaveTransform zapnans temp
variable lastvalue=temp[numpnts(temp)-1]
FindValue/R/V=(lastvalue) input
return V_value
end
function lastNonZero2(wave input)
int i=numpnts(input)-1
for(;i>=0;i-=1)
if(input[i])
break
endif
endfor
return i
end
Try:
16
•print lastnonzero2(mywave)
16
September 30, 2024 at 09:47 am - Permalink
Here is another solution that works with your data:
Make/O test = {2,5,8,0,1,4,33,6,3,7,0,8,0,3,1,8,99,0,0,0,0,0,0,0,0}
Reverse test; FindLevel/P/Q test, 0; Reverse test;
int point = numpnts(test)-V_LevelX-1
point -= 1 // -1 added 2024-10-01
Print point
End
September 30, 2024 at 10:21 am - Permalink
In reply to Hmm... somehow Andy's code… by chozo
That it no more decaf! Thanks for the corrections Chozo.
Andy
September 30, 2024 at 10:38 am - Permalink
Here is another solution that eliminates the need for Reverse using /R with swap parameters:
Make/O test = {2,5,8,0,1,4,33,6,3,7,0,8,0,3,1,8,99,0,0,0,0,0,0,0,0}
int numPoints = numpnts(test)
FindLevel/P/Q/R=(numPoints-1,0) test, 0
int point = V_LevelX - 1 // -1 added 2024-10-01
Print point
End
September 30, 2024 at 10:50 am - Permalink
... or you can use MatrixOP:
The index of the last non-zero element of the wave ddd is:
The data at that wave point is:
print ddd[aa[0]]
September 30, 2024 at 04:42 pm - Permalink
I think that you need to subtract one from the index in hrodstein's solutions if you want to find the last non-zero point.
You can construct for yourself an equivalent to numpy's nonzero:
MatrixOP/free wOut = zapINFs(indexRows(w)/(1-equal(w,0)))
return wOut
end
October 1, 2024 at 01:53 am - Permalink
Here's yet another solution. It may be that Extract does more work than necessary, but it's simple and easy to understand:
Extract/INDX/FREE source, nonzeroIndex, source != 0
return nonzeroIndex[inf]
end
October 1, 2024 at 09:41 am - Permalink
Tony is right. My solutions found the last zero value. I have corrected them. Thanks Tony.
October 1, 2024 at 09:52 am - Permalink