I have a dataframe:
df = pd.DataFrame({'A': [1,2,-2,0,0], 'B': [0, 0, 0, 3, -2], 'C' : [0, 0, -2, 4, 0], 'D': [0, -3, 2, 1, -2]} )
Out:
A B C D
0 1 0 0 0
1 2 0 0 -3
2 -2 0 -2 2
3 0 3 4 1
4 0 -2 0 -2
For each column , if the last non-zero value < 0: repace it with 0.
expected result:
df_end = pd.DataFrame({'A': [1,2,0,0,0], 'B': [0, 0, 0, 3, 0], 'C' : [0, 0, -2, 4, 0], 'D': [0, -3, 2, 1, 0]} )
df_end
Out:
A B C D
0 1 0 0 0
1 2 0 0 -3
2 0 0 -2 2
3 0 3 4 1
4 0 0 0 0
I have solved the opposite problem (if first non-zero value < 0, replace with 0) with:
df.where(df.gt(0).cummax(),0)
I now need it to look at the table from the bottom.
#EDIT As was pointed out in the comments, df.where(df.gt(0).cummax(),0) will eliminate all - values until the first positive. In my original Dataframe Positive and negative values always alternate, so df.where(df.gt(0).cummax(),0) works. I made a bad example dataframe.
Let's try iloc[::-1]
to revert df
:
df[~df.iloc[::-1].gt(0).cummax()] = 0
Output:
A B C D
0 1 0 0 0
1 2 0 0 -3
2 0 0 -2 2
3 0 3 4 1
4 0 0 0 0
Update : As @Ben.T commented, in the case you have several negative endings, the above would turn them all into zero. This would fix that:
df = pd.DataFrame({'A': [1,2,-2,-1,0], 'B': [0, 0, 0, 3, -2], 'C' : [0, 0, -2, 4, 0], 'D': [0, -3, 2, 1, -2]} )
s = df.iloc[::-1]
df[s.lt(0).cumsum().eq(1) & (~s.gt(0).cummax())] = 0
Output:
A B C D
0 1 0 0 0
1 2 0 0 -3
2 -2 0 -2 2
3 0 3 4 1
4 0 0 0 0
This will only replace the last negative value to 0
s=np.sign(df).iloc[::-1].eq(-1).idxmax()
df.values[s,df.columns.get_indexer(s.index)]=0
df
A B C D
0 1 0 0 0
1 2 0 0 -3
2 0 0 0 2
3 0 3 4 1
4 0 0 0 0
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.