我想用数据框做一些计算
ID | 方法 | 国家 | 数量 | 成功 |
---|---|---|---|---|
95 | Мир | 白俄罗斯 | 6063 | 0 |
96 | 大师 | 日本 | 4013 | 0 |
97 | 美国运通 | 白俄罗斯 | 1426 | 1 |
98 | 大师 | 白俄罗斯 | 5692 | 1 |
99 | 万事达卡 | 俄罗斯 | 6929 | 1 |
我想按方法和国家、付款次数、成功率和成功付款总额计算平均金额。
Success Rate = (Number of payments where Success = 1) / All payments
在 SQL 中,我会做到这一点非常简单
SELECT country,
method,
avg(amount),
count(1),
count(CASE WHEN success = 1 THEN id END) / count(1) AS conversion,
sum(CASE WHEN success = 1 THEN amount END) sum_success,
FROM data
GROUP BY country, method;
前两个计算在 Python 中也相对简单。
df.groupby(['Country', 'Method']).agg({'Amount': ['mean', 'count']})
但第三、第四次计算似乎不太可能,不费吹灰之力。
有没有办法快速优雅地做到这一点?
请不要说我可以通过采用 Success 列的 mean() 来计算成功率。我知道。我已经简化了我实际要做的事情,我的真正任务无法通过这种方式解决。
答案 0 :(得分:3)
SQL 可以在返回结果之前解析您的语句(它甚至可以找出列名,即使它们是大写或小写的)- 只要您使用正确的关键字,SQL 就可以轻松实现这种方式;在 Pandas 中,通常情况下,您必须明确;在这种情况下,您必须在聚合之前预先创建一些列 - 通常情况下,这样做会更快:
# create the columns that will be needed
(df.assign(sum_success = lambda df: df.Amount.where(df.Success==1),
conversion = lambda df:df.Success.eq(1))
.groupby(['Country', 'Method'])
.agg(Amount=('Amount', 'mean'),
count=('Amount', 'size'),
conversion=('conversion', 'sum'),
sum_success = ('sum_success', 'sum'))
.reset_index() # indexes are useful, so you may not reset ... it depends
)
Country Method Amount count conversion sum_success
0 Belarus American Express 1426.0 1 1 1426.0
1 Belarus Maestro 5692.0 1 1 5692.0
2 Belarus Мир 6063.0 1 0 0.0
3 Japan Maestro 4013.0 1 0 0.0
4 Russia Mastercard 6929.0 1 1 6929.0
注意 conversion
,我不必创建条件本身,我只是使用布尔结果并将其汇总到 agg 部分。因此,根据聚合情况,您可能需要使其适应 Pandas 的细微差别。
顺便说一句,Python 中还有另一种数据处理 - datatable
,它允许嵌套计算,类似于 SQL。它仍在增长,但不像熊猫那样功能丰富。
答案 1 :(得分:1)
我们可以尝试采用 mean
where values eq
的情况(1):
df.groupby(['Country', 'Method']).agg({'Amount': ['mean', 'count'],
'Success': lambda s: s.eq(1).mean()})
Amount Success
mean count <lambda>
Country Method
Belarus American Express 1426.0 1 1.0
Maestro 5692.0 1 1.0
Мир 6063.0 1 0.0
Japan Maestro 4013.0 1 0.0
Russia Mastercard 6929.0 1 1.0
DataFrame 构造函数:
df = pd.DataFrame({
'ID': [95, 96, 97, 98, 99],
'Method': ['Мир', 'Maestro', 'American Express', 'Maestro', 'Mastercard'],
'Country': ['Belarus', 'Japan', 'Belarus', 'Belarus', 'Russia'],
'Amount': [6063, 4013, 1426, 5692, 6929],
'Success': [0, 0, 1, 1, 1]
})