Pandas: replace zero value with value of another column

Question:

How to replace zero value in a column with value from same row of another column where previous row value of column is zero i.e. replace only where non-zero has not been encountered yet?
For example: Given a dataframe with columns a, b and c:

+----+-----+-----+----+
|    |   a |   b |  c |
|----+-----+-----|----|
|  0 |   2 |   0 |  0 |
|  1 |   5 |   0 |  0 |
|  2 |   3 |   4 |  0 |
|  3 |   2 |   0 |  3 |
|  4 |   1 |   8 |  1 |
+----+-----+-----+----+

replace zero values in b and c with values of a where previous value is zero

+----+-----+-----+----+
|    |   a |   b |  c |
|----+-----+-----|----|
|  0 |   2 |   2 |  2 |
|  1 |   5 |   5 |  5 |
|  2 |   3 |   4 |  3 |
|  3 |   2 |   0 |  3 | <-- zero in this row is not replaced because of  
|  4 |   1 |   8 |  1 |     non-zero value (4) in row before it.
+----+-----+-----+----+
Asked By: DougKruger

||

Answers:

In [90]: (df[~df.apply(lambda c: c.eq(0) & c.shift().fillna(0).eq(0))]
    ...:    .fillna(pd.DataFrame(np.tile(df.a.values[:, None], df.shape[1]),
    ...:                         columns=df.columns, index=df.index))
    ...:    .astype(int)
    ...: )
Out[90]:
   a  b  c
0  2  2  2
1  5  5  5
2  3  4  3
3  2  0  3
4  1  8  1

Explanation:

In [91]: df[~df.apply(lambda c: c.eq(0) & c.shift().fillna(0).eq(0))]
Out[91]:
   a    b    c
0  2  NaN  NaN
1  5  NaN  NaN
2  3  4.0  NaN
3  2  0.0  3.0
4  1  8.0  1.0

now we can fill NaN’s with the corresponding values from the DF below (which is built as 3 concatenated a columns):

In [92]: pd.DataFrame(np.tile(df.a.values[:, None], df.shape[1]), columns=df.columns, index=df.index)
Out[92]:
   a  b  c
0  2  2  2
1  5  5  5
2  3  3  3
3  2  2  2
4  1  1  1

I am a novice with Excel. Could you please explain your steps in a bit more detail for me? I really need to run your solution in my worksheet but do not have an idea of how and where to input your solution.

Answered By: Derrick
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.