【问题标题】:Pandas: assign mean values to a categoryPandas:将平均值分配给一个类别
【发布时间】:2019-12-11 05:05:42
【问题描述】:

我的数据包括发票和客户。一位客户可以有多张发票。一张发票始终属于一位客户。发票每天更新(报告日期)。

我想计算每个客户的所有发票之间的过帐日期的平均间隔(参见下面的列)。

为了更简单的解释:我想知道每个客户在他/她收到的发票的过帐日期之间的平均间隔(以天为单位)。

Report Date  Invoice No   Customer No  Posting Date   Mean-Interval (days)
2018-08-14   A            1            2018-08-05     3,5
2018-08-14   B            1            2018-08-10     3,5
2018-08-14   C            2            2018-08-01     15

2018-08-15   A            1            2018-08-05     3,5       
2018-08-15   B            1            2018-08-10     3,5       
2018-08-15   C            2            2018-08-01     15

2018-08-16   C            2            2018-08-01     15
2018-08-16   D            1            2018-08-12     3,5
2018-08-16   E            2            2018-08-16     15

所以客户 1 在 2018 年 8 月 5 日收到发票 A,在 2018 年 8 月 10 日收到发票 B,在 2018 年 8 月 12 日收到发票 D。

所有收到发票日期之间的平均间隔为: (5+2)/2 = 3.5 天

我编写的代码计算发布日期之间的平均间隔(按“发票编号”分组)。

但它只适用于一个特定的客户编号“A”。但是,我需要为每个客户计算并分配到如上所示的表中。

从技术上讲,我可以使用 for 循环来解决这个问题。但是对于大约 2 万名客户,这将花费太长时间。

dateMean = df[df["Customer No"] == "A"].sort_values(by='Posting Date').groupby('Invoice No', sort=False)\
        .agg({'Posting Date': 'first'})["Posting Date"]

dateMean.diff().mean()

Out: Timedelta('3 days 12:00:00')

请注意,可以在同一日期创建多个发票。这就是为什么我总是取发票的第一个日期并将其与另一个过帐日期的发票进行比较。

【问题讨论】:

    标签: python python-3.x pandas pandas-groupby


    【解决方案1】:

    sortdrop_duplicates 获取唯一发票。然后我们可以计算平均时间差并将结果映射回原来的。

    import pandas as pd
    
    #df['Report Date'] = pd.to_datetime(df['Report Date'])
    #df['Posting Date'] = pd.to_datetime(df['Posting Date'])
    
    cols = ['Customer No', 'Invoice No']
    df1 = df.sort_values(cols).drop_duplicates(cols)
    
    # `m` so diff is only within user. 
    m = df1['Customer No'].eq(df1['Customer No'].shift())
    
    # `s`: Series of average time diff, index is Customer No
    s = df1['Posting Date'].diff().where(m).dt.days.groupby(df1['Customer No']).mean()
    
    df['Mean-Interval (days)'] = df['Customer No'].map(s)
    

    print(df)
    
      Report Date Invoice No  Customer No Posting Date  Mean-Interval (days)
    0  2018-08-14          A            1   2018-08-05                   3.5
    1  2018-08-14          B            1   2018-08-10                   3.5
    2  2018-08-14          C            2   2018-08-01                  15.0
    3  2018-08-15          A            1   2018-08-05                   3.5
    4  2018-08-15          B            1   2018-08-10                   3.5
    5  2018-08-15          C            2   2018-08-01                  15.0
    6  2018-08-16          C            2   2018-08-01                  15.0
    7  2018-08-16          D            1   2018-08-12                   3.5
    8  2018-08-16          E            2   2018-08-16                  15.0
    

    【讨论】:

    • 这很好用!谢谢!此外:这个例子教会了我很多。
    猜你喜欢
    • 2018-08-23
    • 1970-01-01
    • 1970-01-01
    • 2021-01-10
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-18
    相关资源
    最近更新 更多