Pandas:更改多索引系列的重复项
Pandas: Change duplicates respecting multiindex series
以这个多指数系列为例:
client_id y-m
0 2018-05 13.935563
2018-06 5326.898967
2018-07 11968.431680
2018-08 NaN
2018-09 NaN
2018-10 15257.418813
2018-11 NaN
2018-12 20509.774900
2019-01 25187.485960
2019-02 NaN
2019-03 NaN
2019-04 NaN
2019-05 NaN
2019-06 NaN
2019-07 NaN
2019-08 35943.419296
2019-09 38253.756910
2019-10 42289.134021
2019-11 NaN
2019-12 NaN
2020-01 NaN
2020-02 NaN
2020-03 NaN
2020-11 NaN
2020-12 NaN
2021-01 NaN
1 2019-07 169.805400
2019-08 169.805400
2019-09 169.805400
2019-10 169.805400
2019-11 169.805400
2019-12 NaN
2020-01 NaN
2020-07 NaN
2020-08 NaN
2021-01 NaN
考虑到第一个索引 client_id
,我想用 NaN 替换重复值,同时保持第一个值。重要的是只替换第一级索引的重复项。
对于上面的示例数据,client_id == 1
的重复值序列应仅保留2019-07
的值,其他应设置为NaN,如下所示:
1 2019-07 169.805400
1 2019-08 NaN
1 2019-09 NaN
1 2019-10 NaN
如果重复的值是连续的,则可以按第一个索引分组并使用shift
。这将为您提供一个布尔掩码,可用于将重复值设置为 NaN。
代码:
mask = s.groupby('client_id').shift() == s
s.loc[mask] = np.nan
如果不能保证重复项是连续的,那么您可以先对值进行排序并应用上述解决方案:
s = s.sort_values()
mask = s.groupby('client_id').shift() == s
s.loc[mask] = np.nan
s = s.sort_index()
然后按索引排序return到原来的顺序。
另一种解决方案是将 duplicated
应用于每个组:
s.loc[s.groupby('client_id').apply(lambda x: x.duplicated(keep='first'))] = np.nan
所有解决方案的结果将是:
client_id y-m
0 2018-05 13.935563
2018-06 5326.898967
2018-07 11968.431680
2018-08 NaN
2018-09 NaN
2018-10 15257.418813
2018-11 NaN
2018-12 20509.774900
2019-01 25187.485960
2019-02 NaN
2019-03 NaN
2019-04 NaN
2019-05 NaN
2019-06 NaN
2019-07 NaN
2019-08 35943.419296
2019-09 38253.756910
2019-10 42289.134021
2019-11 NaN
2019-12 NaN
2020-01 NaN
2020-02 NaN
2020-03 NaN
2020-11 NaN
2020-12 NaN
2021-01 NaN
1 2019-07 169.805400
2019-08 NaN
2019-09 NaN
2019-10 NaN
2019-11 NaN
2019-12 NaN
2020-01 NaN
2020-07 NaN
2020-08 NaN
2021-01 NaN
以这个多指数系列为例:
client_id y-m
0 2018-05 13.935563
2018-06 5326.898967
2018-07 11968.431680
2018-08 NaN
2018-09 NaN
2018-10 15257.418813
2018-11 NaN
2018-12 20509.774900
2019-01 25187.485960
2019-02 NaN
2019-03 NaN
2019-04 NaN
2019-05 NaN
2019-06 NaN
2019-07 NaN
2019-08 35943.419296
2019-09 38253.756910
2019-10 42289.134021
2019-11 NaN
2019-12 NaN
2020-01 NaN
2020-02 NaN
2020-03 NaN
2020-11 NaN
2020-12 NaN
2021-01 NaN
1 2019-07 169.805400
2019-08 169.805400
2019-09 169.805400
2019-10 169.805400
2019-11 169.805400
2019-12 NaN
2020-01 NaN
2020-07 NaN
2020-08 NaN
2021-01 NaN
考虑到第一个索引 client_id
,我想用 NaN 替换重复值,同时保持第一个值。重要的是只替换第一级索引的重复项。
对于上面的示例数据,client_id == 1
的重复值序列应仅保留2019-07
的值,其他应设置为NaN,如下所示:
1 2019-07 169.805400
1 2019-08 NaN
1 2019-09 NaN
1 2019-10 NaN
如果重复的值是连续的,则可以按第一个索引分组并使用shift
。这将为您提供一个布尔掩码,可用于将重复值设置为 NaN。
代码:
mask = s.groupby('client_id').shift() == s
s.loc[mask] = np.nan
如果不能保证重复项是连续的,那么您可以先对值进行排序并应用上述解决方案:
s = s.sort_values()
mask = s.groupby('client_id').shift() == s
s.loc[mask] = np.nan
s = s.sort_index()
然后按索引排序return到原来的顺序。
另一种解决方案是将 duplicated
应用于每个组:
s.loc[s.groupby('client_id').apply(lambda x: x.duplicated(keep='first'))] = np.nan
所有解决方案的结果将是:
client_id y-m
0 2018-05 13.935563
2018-06 5326.898967
2018-07 11968.431680
2018-08 NaN
2018-09 NaN
2018-10 15257.418813
2018-11 NaN
2018-12 20509.774900
2019-01 25187.485960
2019-02 NaN
2019-03 NaN
2019-04 NaN
2019-05 NaN
2019-06 NaN
2019-07 NaN
2019-08 35943.419296
2019-09 38253.756910
2019-10 42289.134021
2019-11 NaN
2019-12 NaN
2020-01 NaN
2020-02 NaN
2020-03 NaN
2020-11 NaN
2020-12 NaN
2021-01 NaN
1 2019-07 169.805400
2019-08 NaN
2019-09 NaN
2019-10 NaN
2019-11 NaN
2019-12 NaN
2020-01 NaN
2020-07 NaN
2020-08 NaN
2021-01 NaN