[英]Python pandas - what is the proper way to NaN all zeros before first non-zero value in multiple columns?
我有一个df
列date
, a
, b
和id
。 id
是分组的, date
值在转到新的id
时重复。 在a
和b
列中,我想在每个id
中的第一个非零值之前用nan
替换 0 。 因此,使用以下数据:
df = pd.DataFrame({
'date': ['2019-01-01', '2019-02-01', '2019-03-01', '2019-04-01', '2019-05-01']*3,
'id': [0,0,0,0,0,1,1,1,1,1,2,2,2,2,2],
'a': [0,0,10,40,20,0,0,0,50,90,0,0,0,0,0],
'b': [0,0,0,123,345,0,0,555,0,666,0,0,0,0,30]
})
date id a b
0 2019-01-01 0 0 0
1 2019-02-01 0 0 0
2 2019-03-01 0 10 0
3 2019-04-01 0 40 123
4 2019-05-01 0 20 345
5 2019-01-01 1 0 0
6 2019-02-01 1 0 0
7 2019-03-01 1 0 555
8 2019-04-01 1 50 0
9 2019-05-01 1 90 666
10 2019-01-01 2 0 0
11 2019-02-01 2 0 0
12 2019-03-01 2 0 0
13 2019-04-01 2 0 0
14 2019-05-01 2 0 30
output 应该是
date id a b
0 2019-01-01 0 NaN NaN
1 2019-02-01 0 NaN NaN
2 2019-03-01 0 10.0 NaN
3 2019-04-01 0 40.0 123.0
4 2019-05-01 0 20.0 345.0
5 2019-01-01 1 NaN NaN
6 2019-02-01 1 NaN NaN
7 2019-03-01 1 NaN 555.0
8 2019-04-01 1 50.0 0.0
9 2019-05-01 1 90.0 666.0
10 2019-01-01 2 0.0 NaN
11 2019-02-01 2 0.0 NaN
12 2019-03-01 2 0.0 NaN
13 2019-04-01 2 0.0 NaN
14 2019-05-01 2 0.0 30.0
请注意,如果列中给定id
的所有值都为零,则保留零。
我目前的解决方案是 2 个for
-loops:一个用于列,一个用于id
上的groupby
对象; 我认为有改进空间的解决方案。 任何提示/帮助将不胜感激。
for col in ['a', 'b']:
for i, grp in df.groupby('id'):
min_idx = grp.index.min()
non_z_idx = grp[grp[col] > 0].index.min()
if not np.isnan(non_z_idx):
df.loc[min_idx:non_z_idx - 1, col] = np.nan
使用 2 个面具和df.where
m1 = df[['a','b']].ne(0).groupby(df.id).cummax()
m2 = df[['a','b']].eq(0).groupby(df.id).transform('all')
df[['a','b']] = df[['a','b']].where(m1 | m2)
Out[88]:
date id a b
0 2019-01-01 0 NaN NaN
1 2019-02-01 0 NaN NaN
2 2019-03-01 0 10.0 NaN
3 2019-04-01 0 40.0 123.0
4 2019-05-01 0 20.0 345.0
5 2019-01-01 1 NaN NaN
6 2019-02-01 1 NaN NaN
7 2019-03-01 1 NaN 555.0
8 2019-04-01 1 50.0 0.0
9 2019-05-01 1 90.0 666.0
10 2019-01-01 2 0.0 NaN
11 2019-02-01 2 0.0 NaN
12 2019-03-01 2 0.0 NaN
13 2019-04-01 2 0.0 NaN
14 2019-05-01 2 0.0 30.0
如果您不想要 2 个 groupby,您可以将一个 groupby 与apply
m = df[['a','b']].ne(0).groupby(df.id).apply(lambda x: x.cummax() | ~x.any())
df[['a','b']] = df[['a','b']].where(m)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.