Python: How to set values of zero in a list/array/pd.Series to be the next non-zero value?
Question: I have a Python list-like structure with more than 1 million elements. Each
element takes one of three possible values, namely `-1`, `0`, or `1`. What I'm
trying to achieve is to replace all the zeros with the next non-zero value.

For instance, if I have

    
    
    [1, 0, 0, -1, 0, 1, 0, 0, 0, -1]
    

after the operation I'll have

[1, **_-1_** , **_-1_** , -1, **_1_** , 1, **_-1_** , **_-1_** , **_-1_** ,
-1].

I can have a nested loop structure to achieve this goal, but with more than 1
million elements in the list, it's taking forever to run. Does anyone know a
faster algorithm that'll achieve this goal?


Answer: You can try first create `Series`, then
[`replace`](http://pandas.pydata.org/pandas-
docs/stable/generated/pandas.Series.replace.html) `0` to `NaN` and last use
[`fillna`](http://pandas.pydata.org/pandas-
docs/stable/generated/pandas.Series.fillna.html):

    
    
    import pandas as pd
    import numpy as np
    
    li = [1, 0, 0, -1, 0, 1, 0, 0, 0, -1]
    s = pd.Series(li)
    print s
    0    1
    1    0
    2    0
    3   -1
    4    0
    5    1
    6    0
    7    0
    8    0
    9   -1
    dtype: int64
    
    
    print s.replace({0:np.nan})
    0     1
    1   NaN
    2   NaN
    3    -1
    4   NaN
    5     1
    6   NaN
    7   NaN
    8   NaN
    9    -1
    dtype: float64
    
    
    
    print s.replace({0:np.nan}).fillna(method='bfill')
    0    1
    1   -1
    2   -1
    3   -1
    4    1
    5    1
    6   -1
    7   -1
    8   -1
    9   -1
    dtype: float64
    

Or instead `replace` use [`loc`](http://pandas.pydata.org/pandas-
docs/stable/generated/pandas.Series.loc.html), then convert to int by
[`astype`](http://pandas.pydata.org/pandas-
docs/stable/generated/pandas.Series.astype.html) and last use
[`tolist`](http://pandas.pydata.org/pandas-
docs/stable/generated/pandas.Series.tolist.html):

    
    
    s.loc[s == 0] = np.nan
    
    s.loc[s == 0] = np.nan
    print s.fillna(method='bfill').astype(int).tolist()
    [1, -1, -1, -1, 1, 1, -1, -1, -1, -1]
    

