Reputation: 1282
I would like to remove preceding and trialing zero values row-wise in my df and then have them shift to be 'aligned'.
Probably best demonstrated with the below example.
Initial df:
index c1 c2 c3 c4 c5 c6 c7 c8
1 0 0 1 2 3 4 5 0
2 0 0 0 1 2 3 4 5
3 0 1 2 3 0 0 0 0
4 0 0 1 2 3 4 0 0
5 1 2 3 4 5 6 7 0
6 0 0 0 1 0 0 4 0
Output:
index c1 c2 c3 c4 c5 c6 c7
1 1 2 3 4 5
2 1 2 3 4 5
3 1 2 3
4 1 2 3 4
5 1 2 3 4 5 6 7
6 1 0 0 4
Note that there is potential to be zeroes within the "string" of true values so need to stop at the first / reverse first occurrence. Is this possible? Thanks.
Upvotes: 2
Views: 2536
Reputation: 153560
You can use this:
df_out = df.apply(lambda x: pd.Series(x.loc[x.mask(x == 0).first_valid_index():
x.mask(x == 0).last_valid_index()].tolist()),
axis=1)
df_out.set_axis(df.columns[df_out.columns], axis=1, inplace=False)
Output:
c1 c2 c3 c4 c5 c6 c7
index
1 1.0 2.0 3.0 4.0 5.0 NaN NaN
2 1.0 2.0 3.0 4.0 5.0 NaN NaN
3 1.0 2.0 3.0 NaN NaN NaN NaN
4 1.0 2.0 3.0 4.0 NaN NaN NaN
5 1.0 2.0 3.0 4.0 5.0 6.0 7.0
6 1.0 0.0 0.0 4.0 NaN NaN NaN
N
Upvotes: 3
Reputation: 51185
Using np.trim_zeros
:
Trim the leading and/or trailing zeros from a 1-D array or sequence.
out = pd.DataFrame([np.trim_zeros(i) for i in df.values], index=df.index)
out.columns = df.columns[:len(out.columns)]
c1 c2 c3 c4 c5 c6 c7
index
1 1 2 3 4.0 5.0 NaN NaN
2 1 2 3 4.0 5.0 NaN NaN
3 1 2 3 NaN NaN NaN NaN
4 1 2 3 4.0 NaN NaN NaN
5 1 2 3 4.0 5.0 6.0 7.0
6 1 0 0 4.0 NaN NaN NaN
Upvotes: 6