使用 Pandas 计算 C 列中所有小于 R 行日期的日期的平均值

问题描述 投票:0回答:1

我有一个包含 >101K 行的 pandas 数据框,我试图根据日期计算

won
列的平均值。逻辑是,对于每一行,找到
won
row['created_on']
的所有行的 < current
row['created_on']
的平均值。请注意,我并不是试图获得
won
列的累积平均值 ,因为这个问题被识别为重复的。建议的重复项提供了一种按行计算累积值的方法,但我希望尝试按 date 计算累积值,即
rolling_won_prop
的所有值对于给定日期应该相同,但不应该是按行累积。

我可以用

计算一个简单的值
def get_win_prop(df, d) -> float:
    mask = (df['created_on'] < d)
    prop = df[mask].won.mean()
    return(prop)

get_win_prop(d, '2022-10-25')

当我尝试将此函数与

pd.assign()
一起使用时,我没有收到任何错误,但所有值最终都是
NaN
:

d.assign(rolling_won_prop = lambda x: get_win_prop(x, x.created_on))

enter image description here

我错过了什么?我会假设

get_win_prop()
fx 就是我所需要的。在 pandas 中是否有更有效的方法来做到这一点?请注意,我在下面提供了数据示例,但在计算
get_win_prop()
值之前,我需要按客户 ID 列进行分组。

更新1

我提出了一个适用于下面这个玩具数据集的示例解决方案,但可能无法很好地扩展:

result = []
for i in d.created_on.unique():
    prev_vals = d[d['created_on'] < i]
    result.append(prev_vals.won.mean())


d.merge(pd.DataFrame({'created_on': d.created_on.unique(), 
                      'rolling_won_prop ': result}), how = 'left')

enter image description here

更新2

我用一个

for
循环拼凑了一个不优雅的解决方案,但产生了适当的结果:

results = []

for i in d.created_on.unique():
    prev_vals = d[d['created_on'] < i]
    results.append(prev_vals.won.mean())


d.merge(pd.DataFrame({'created_on': d.created_on.unique(), 
                       'rolling_won_prop ': results}), how = 'left')

enter image description here

鉴于我有一个额外的客户 ID 列(此处提供的 MWE 中不存在),我可以将上述解决方案调整为按客户 ID 进行分组,但这仍然不是一个主意。如果可能的话,我宁愿在 pandas 框架中使用这个解决方案。

样本数据

import pandas as pd
from pandas import Timestamp

d = pd.DataFrame({'created_on': [Timestamp('2022-09-22 00:00:00'), Timestamp('2022-10-14 00:00:00'),Timestamp('2022-10-19 00:00:00'),Timestamp('2022-10-25 00:00:00'),Timestamp('2022-11-02 00:00:00'),
                Timestamp('2022-11-04 00:00:00'),Timestamp('2022-11-16 00:00:00'),Timestamp('2022-11-28 00:00:00'),Timestamp('2022-11-28 00:00:00'),Timestamp('2022-12-07 00:00:00'),
                Timestamp('2022-12-21 00:00:00'),Timestamp('2022-12-21 00:00:00'),Timestamp('2022-12-21 00:00:00'),Timestamp('2022-12-21 00:00:00')],
  'n_lines': [7, 3, 7, 6, 6, 4, 5, 3, 10, 3, 6, 6, 9, 6],
  'n_pieces': [606, 202, 706, 765, 255, 803, 1004, 2702, 1909, 546, 555, 555, 558,555],
  'quote_total': [1780.4299999999998, 3575.4600000000005, 11762.079999999994, 6725.160000000002, 995.9300000000001, 1644.2100000000003, 2620.2299999999996,
                   8082.090000000001, 5302.320000000001, 1959.7599999999998, 8734.67, 9792.3, 0.0, 9720.71],
  'won': [1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0]})
python pandas
1个回答
0
投票

假设日期按“id”排序,您仍然可以从链接的帖子中受益。您只需随后用第一个值填充

['id', 'group']
的重复组合即可。含义:

最小可重现示例,包含

'id'

import pandas as pd
import numpy as np

data = {'id': np.repeat(['A', 'B'], [6,6]),
        'created_on': np.tile(np.repeat(pd.date_range('2024-01-01', periods=4), 
                                        [1,2,1,2]), 2),
        'won': np.tile([1, 0], 6)}

df = pd.DataFrame(data)

df

   id created_on  won
0   A 2024-01-01    1
1   A 2024-01-02    0
2   A 2024-01-02    1
3   A 2024-01-03    0
4   A 2024-01-04    1
5   A 2024-01-04    0
6   B 2024-01-01    1
7   B 2024-01-02    0
8   B 2024-01-02    1
9   B 2024-01-03    0
10  B 2024-01-04    1
11  B 2024-01-04    0

代码

gp = df.groupby('id')['won']
df['rolling_won_prop'] = (gp.cumsum() - df['won'])/gp.cumcount()
df['rolling_won_prop'] = (df.groupby(['id', 'created_on'])
                          ['rolling_won_prop'].transform('first')
                          )

输出:

   id created_on  won  rolling_won_prop
0   A 2024-01-01    1               NaN
1   A 2024-01-02    0          1.000000
2   A 2024-01-02    1          1.000000 
3   A 2024-01-03    0          0.666667 # e.g. (1 + 0 + 1) / 3
4   A 2024-01-04    1          0.500000 # e.g. (1 + 0 + 1 + 0) / 4
5   A 2024-01-04    0          0.500000 # filled from prev row
6   B 2024-01-01    1               NaN
7   B 2024-01-02    0          1.000000
8   B 2024-01-02    1          1.000000
9   B 2024-01-03    0          0.666667
10  B 2024-01-04    1          0.500000
11  B 2024-01-04    0          0.500000
© www.soinside.com 2019 - 2024. All rights reserved.