python - Pandas:将所有<= 0的值按组设置为列中的最大值,但仅在该组中的最后一个正值之后
问题描述
我正在尝试按组将所有 <= 0 的值设置为该组中的最大值,但仅在最后一个正值之后。也就是说,必须忽略组中最后一个正值之前的所有值 <=0。例子:
data = {'group':['A', 'A', 'A', 'A', 'A', 'B', 'B',
'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C', 'C'],
'value':[3, 0, 8, 7, 0, -1, 0, 9, -2, 0, 0, 2, 0, 5, 0, 1]}
df = pd.DataFrame(data)
df
group value
0 A 3
1 A 0
2 A 8
3 A 7
4 A 0
5 B -1
6 B 0
7 B 9
8 B -2
9 B 0
10 B 0
11 C 2
12 C 0
13 C 5
14 C 0
15 C 1
结果必须是:
group value
0 A 3
1 A 0
2 A 8
3 A 7
4 A 8
5 B -1
6 B 0
7 B 9
8 B 9
9 B 9
10 B 9
11 C 2
12 C 0
13 C 5
14 C 0
15 C 1
谢谢指教
解决方案
首先添加一列来标识具有负值的行(更准确地说 <= 0):
df['neg'] = (df['value'] <= 0)
然后,对于每个组,找到'neg'
设置为 True 且连续的最后几个条目的序列。为此,请颠倒 DataFrame 的顺序(带.iloc[::-1]
),然后.cumprod()
在'neg'
列上使用。cumprod()
会将 True 视为 1,将 False 视为 0,因此只要您看到所有 True,累积乘积将为 1,并且一旦您看到第一个 False,累积乘积就会变为并保持为 0。由于我们颠倒了顺序,所以我们从末尾倒退,所以我们在末尾找到 True 的序列。
df['upd'] = df.iloc[::-1].groupby('group')['neg'].cumprod().astype(bool)
现在我们知道要更新哪些条目,我们只需要知道将它们更新到什么,这是组的最大值。我们可以transform('max')
在 groupby 上使用来获取该值,然后剩下的就是对设置的'value'
位置进行实际更新'upd'
:
df.loc[df['upd'], 'value'] = df.groupby('group')['value'].transform('max')
我们可以通过删除我们在该过程中使用的两个辅助列来完成:
df = df.drop(['neg', 'upd'], axis=1)
我得到的结果与您的预期结果相符。
更新:或者在单个(长!)行中执行整个操作,而不向原始 DataFrame 添加任何辅助列:
df.loc[
df.assign(
neg=(df['value'] <= 0)
).iloc[::-1].groupby(
'group'
)['neg'].cumprod().astype(bool),
'value'
] = df.groupby(
'group'
)['value'].transform('max')
推荐阅读
- python - ValueError: 操作数不能与形状 (7,) (6,) (7,) 一起广播
- ruby-on-rails - Rails 中与月份相关的文本
- laravel - Laravel 5.7:确定文件夹的总大小(以 MB 为单位)
- symfony - symfony 注释访问另一个字段
- arrays - 在 Flutter 中从 JSON 响应创建表
- c++ - 断言结构类型是用 alignas() 声明的
- asterisk - 星号 指新的 IP 地址
- linux - 如何在外壳上正确超时尾部管道
- regex - Shopify 用于结帐过程的正则表达式
- javascript - 有没有办法更改弹出的 create-react-app 的 eslint 规则?