熊猫:为类别指定平均值

时间:2019-08-02 14:39:59

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

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

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

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

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-08-05收到发票A,在2018-08-10收到发票B,在2018-08-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')

请记住,有可能在同一日期创建多个发票。这就是为什么我总是拿发票的第一个日期并将其与另一个过帐日期的发票进行比较的原因。

1 个答案:

答案 0 :(得分:2)

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