find last non-zero element's index in pandas series

  • Last Update :
  • Techknowledgy :

I might just write s[s != 0].index[-1], e.g.

>>> s = pd.Series([0, 1, 2, 3, 0, 4, 0], index = range(7, 14)) >>>
   s
7 0
8 1
9 2
10 3
11 0
12 4
13 0
dtype: int64 >>>
   s[s != 0].index[-1]
12

Originally I thought using nonzero would make things simpler, but the best I could come up with was

>>> s.index[s.nonzero()[0][-1]]
12

A couple of ways it with generator:

max(i
   for i in s.index
   if s[i] != 0) # will work only
if index is sorted

and

next(i
   for i in s.index[::-1]
   if s[i] != 0)

Through numpy's trip_zeros:

import numpy as np
np.trim_zeros(s, 'b').index[-1]

Suggestion : 2

Return the integer indices of the elements that are non-zero.,This method is equivalent to calling numpy.nonzero on the series data. For compatibility with NumPy, the return value is the same (a tuple with an array of indices for each dimension), but it will always be a one-item tuple because series only have one dimension.,Indices of elements that are non-zero.,Deprecated since version 0.24.0: Please use .to_numpy().nonzero() as a replacement.

>>> s = pd.Series([0, 3, 0, 4]) >>>
   s.nonzero()
   (array([1, 3]), ) >>>
   s.iloc[s.nonzero()[0]]
1 3
3 4
dtype: int64
>>> s = pd.Series([0, 3, 0, 4], index = ['a', 'b', 'c', 'd'])
# same
return although index of s is different >>>
   s.nonzero()
   (array([1, 3]), ) >>>
   s.iloc[s.nonzero()[0]]
b 3
d 4
dtype: int64

Suggestion : 3

Last Updated : 30 Sep, 2019

Output:

(array([0, 2, 3, 5, 6, 8, 9]), )
0 1
2 12
3 1
5 4
6 22
8 3
9 9
dtype: int64

Suggestion : 4

Returns a tuple of arrays, one for each dimension of a, containing the indices of the non-zero elements in that dimension. The values in a are always tested and returned in row-major, C-style order.,To group the indices by element, rather than dimension, use argwhere, which returns a row for each non-zero element.,Return indices that are non-zero in the flattened version of the input array.,Return the indices of the elements that are non-zero.

>>> x = np.array([
      [3, 0, 0],
      [0, 4, 0],
      [5, 6, 0]
   ]) >>>
   x
array([
      [3, 0, 0],
      [0, 4, 0],
      [5, 6, 0]
   ]) >>>
   np.nonzero(x)
   (array([0, 1, 2, 2]), array([0, 1, 0, 1]))
>>> x[np.nonzero(x)]
array([3, 4, 5, 6]) >>>
   np.transpose(np.nonzero(x))
array([
   [0, 0],
   [1, 1],
   [2, 0],
   [2, 1]
])
>>> a = np.array([
      [1, 2, 3],
      [4, 5, 6],
      [7, 8, 9]
   ]) >>>
   a > 3
array([
      [False, False, False],
      [True, True, True],
      [True, True, True]
   ]) >>>
   np.nonzero(a > 3)
   (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2]))
>>> a[np.nonzero(a > 3)]
array([4, 5, 6, 7, 8, 9]) >>>
   a[a > 3] # prefer this spelling
array([4, 5, 6, 7, 8, 9])
>>> (a > 3).nonzero()
   (array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2]))

Suggestion : 5

Deprecated since version 0.24.0: Please use .to_numpy().nonzero() as a replacement.,Return the integer indices of the elements that are non-zero.,This method is equivalent to calling numpy.nonzero on the series data. For compatibility with NumPy, the return value is the same (a tuple with an array of indices for each dimension), but it will always be a one-item tuple because series only have one dimension.,Indices of elements that are non-zero.

Examples

>>> s = pd.Series([0, 3, 0, 4]) >>>
   s.nonzero()
   (array([1, 3]), ) >>>
   s.iloc[s.nonzero()[0]]
1 3
3 4
dtype: int64
>>> s = pd.Series([0, 3, 0, 4])
>>> s.nonzero()
(array([1, 3]),)
>>> s.iloc[s.nonzero()[0]]
1    3
3    4
dtype: int64
>>> s = pd.Series([0, 3, 0, 4], index = ['a', 'b', 'c', 'd'])
# same
return although index of s is different >>>
   s.nonzero()
   (array([1, 3]), ) >>>
   s.iloc[s.nonzero()[0]]
b 3
d 4
dtype: int64

Suggestion : 6

👻 See our latest reviews to choose the best laptop for Machine Learning and Deep learning tasks! , Pandas Series.nonzero() — it is a method with no arguments. As the name suggests, by returning non-zero values ‚Äã‚Äãfrom a series, it returns the index of all non-zero values. The returned series of indexes can be passed to the method iloc () to return all nonzero values ‚Äã‚Äãat those indices. , As shown in the output, the index position of each nonzero element was returned, and the values ‚Äã‚Äãin this positions were returned by the iloc method. , 👻 Read also: what is the best laptop for engineering students in 2022?

Exit:

 (array([0, 2, 3, 5, 6, 8, 9]), ) 0 1 2 12 3 1 5 4 6 22 8 3 9 9 dtype: int64

Suggestion : 7

Identify the first & last non-zero elements/indices within a group in numpy,Identify first & last non-zero elements within a group in numpy,Identify first non-zero element within a group in pandas,Identify first non-zero element within group composed of multiple columns in pandas

1._
group = np.array([0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2])
array = np.array([1, 2, 3, 0, 0, 2, 0, 3, 4, 0, 0, 0, 0, 1])
targt = np.array([1, 1, 1, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1])

STEP 1. Find indices of nonzero items of array and mark the startings of new groups

nonzero_idx - > [ * 0, 1, 2, /,*/, 5, /,7,8,/, */,/, /,13] (cross out slashes)
      marker_idx - > [0, 4, 10]

STEP 2. Find starting and ending indices for each group, use np.ufunc.reduceat

starts - > [0, 5, 13]
ends - > [2, 8, 13]

Now, code:

#STEP 1
nonzero = (array != 0)
_, marker_idx = np.unique(group[nonzero], return_index = True)
nonzero_idx = np.arange(len(array))[nonzero]
#STEP 2
starts = np.minimum.reduceat(nonzero_idx, marker_idx)
ends = np.maximum.reduceat(nonzero_idx, marker_idx)
#STEP 3
values = array[starts]
out = np.zeros_like(array)
out[starts] = values
#check the
case we can 't insert the last negative value
if ends[-1] + 1 == len(array):
   out[ends[: -1] + 1] = -values[: -1]
else:
   out[ends + 1] = -values >>>
   np.cumsum(out)
array([1, 1, 1, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1], dtype = int32)

STEP 1. Find indices of nonzero items of array and mark the startings of new groups

nonzero_idx - > [ * 0, 1, 2, /,*/, 5, /,7,8,/, */,/, /,13] (cross out slashes)
      marker_idx - > [0, 4, 10]

STEP 2. Find starting and ending indices for each group, use np.ufunc.reduceat

starts - > [0, 5, 13]
ends - > [2, 8, 13]

STEP 3. Think of an out array such that np.cumsum(out) collapses into target array. Like so:

[1, 0, 0, -1, 0, 2, 0, 0, 0, -2, 0, 0, 0, 1] - > [1, 1, 1, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1]

1

import numpy as np
import pandas as pd

def foo(s):
   chk = np.where(s > 0)[0]
start = min(chk)
end = max(chk)
ans = [True
   if (start <= ind <= end)
   else False
   for ind in range(len(s))
]
return ans

pd.Series(array).groupby(group).transform(
   lambda x: x.mask(foo(x), x[x > 0].iloc[0])).to_numpy()
# array([1, 1, 1, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1])

2

def split(val, grp):
   inds = np.where(np.append(False, grp[1: ] != grp[: -1]))[0]
return np.array_split(val, inds)

def fill(val):
   inds = np.where(val > 0)[0]
start, end = min(inds), max(inds)
val[start: end + 1] = val[start]
return val

np.concatenate([fill(x) for x in split(array, group)])
# array([1, 1, 1, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, 1])