A NumPy array that contains None
and integers will be of typeobject
anyway.
Seems like it it easier to use a list in the first place:
res = []
for x1, x2 in zip(L[:-1], L[1:]):
if (x1 is not None and x2 is None):
res.append(x1)
elif (x1 is None and x2 is not None):
res.append(x2)
None res
is:
[8, 2, 169, 23, 111, 74]
To avoid wrong results when the list does not start or end with None
, limit the search into the part between the first and last None
:
res = []
start = L.index(None)
end = len(L) - L[::-1].index(None)
for x1, x2 in zip(L[start:end-1], L[start+1:end]):
if (x1 is not None and x2 is None):
res.append(x1)
elif (x1 is None and x2 is not None):
res.append(x2)
If you have a NumPy array with NaN instead of None:
a = np.array([np.nan, np.nan, np.nan, np.nan, np.nan, 8, 7, 2, np.nan,
np.nan , np.nan , np.nan, np.nan, np.nan, np.nan, 169, 37, 9,
7 ,23, np.nan , np.nan , 111, 24, 8, 7 , 9, 12 , 74, np.nan])
You can do this in a vectorized way:
b = a[np.isnan(np.roll(a, 1)) | np.isnan(np.roll(a, -1))]
res = b[~np.isnan(b)]
Now res
looks like this:
array([ 8., 2., 169., 23., 111., 74.])
Again, a version with limited
search between first and last NaN:
indices = np.arange(len(a))[np.isnan(a)]
short = a[indices[0]:indices[-1]]
b = short[np.isnan(np.roll(short, 1)) | np.isnan(np.roll(short, -1))]
res = b[~np.isnan(b)]