【问题标题】:How to find the average of last 52 weeks sales at each time in python如何在python中找到每个时间过去52周的平均销售额
【发布时间】:2016-05-05 17:57:50
【问题描述】:

我有一个包含四列的 csv 文件:日期、批发商、产品和销售。我正在寻找每个产品和批发商组合在每个日期最近 52 周的平均销售额。这意味着过去 52 周内在时间“C”时批发商“B”处产品“A”的平均先前销售额是多少。

例如,我们知道批发商“B”的产品“A”在 1 月、4 月、5 月、8 月的销售额分别为 100、200、300、400。假设我们在 1 月之前没有任何记录。因此,批发商 'B' 之前在 4 月销售产品 'A' 的平均值等于 100/1,5 月等于 (200+100)/2 和八月是 (300+200+100)/3。

下表显示了我的数据:

date    wholesaler product  sales
12/31/2012  53929  UPE54     4
12/31/2012  13131  UPE55     1
2/23/2013   13131  UPE55  1156
4/24/2013   13131  UPE55     1
12/1/2013   83389  UPE54     9
12/17/2013  83389  UPE54     1
12/18/2013  52237  UPE54     9
12/19/2013  53929  UME24     1
12/31/2013  82204  UPE55     9
12/31/2013  11209  UME24     4
12/31/2013  52237  UPE54     1

现在我正在使用:

df = pd.read_csv('Sample.csv',index_col='date')

expd_gb = df.reset_index().groupby(['wholesaler', 'product'])['sales'].apply(pd.Series.expanding)
idx = df.reset_index().groupby(['wholesaler', 'product', 'date'])['sales'].count().index

cnct = pd.concat([expd_gb.iloc[n].mean().shift(1) for n in range(len(expd_gb))])
cnct.index = idx

这给出了每个产品-批发商组合的先前销售额的总平均值(不是过去 52 周)。结果是:

wholesaler  product  date      
11209       UME24    12/31/2013      NaN
13131       UPE55    12/31/2012      NaN
                     2/23/2013       1.0
                     4/24/2013     578.5
52237       UPE54    12/18/2013      NaN
                     12/31/2013      9.0
53929       UME24    12/19/2013      NaN
            UPE54    12/31/2012      NaN
82204       UPE55    12/31/2013      NaN
83389       UPE54    12/1/2013       NaN
                     12/17/2013      9.0   

随着时间的推移,销售记录的迭代正在增加。我只需要找出过去 52 周的平均销售额是多少。这意味着在某个日期,例如 2015 年 11 月 6 日,过去 52 周某个批发商的产品平均销售额是多少。感谢一百万您的帮助!

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    考虑一个apply 函数,有条件地平均每条记录的批发商和产品过去 52 周的销售额。如果没有解决方法,groupby() 会为组返回相同的值,而您需要一种运行组平均值,因此请尝试按系列处理。请务必将日期转换为日期时间格式,因为您可以使用 timedelta() 倒计时 52 周。

    import pandas as pd
    import datetime
    
    dateparse = lambda x: pd.datetime.strptime(x, '%m/%d/%Y')
    
    df = pd.read_csv('Sample.csv', index_col='date',
                     parse_dates=[0], date_parser=dateparse)
    
    def last52weeks(x):
        ser = df['sales'][(df.index >= x.name - datetime.timedelta(weeks=52)) &
                          (df.index <= x.name) &
                          (df['wholesaler'] == x[0]) &
                          (df['product'] == x[1])]
        return ser.mean()
    
    df['avg_sales_last52weeks'] = df.apply(last52weeks, axis=1)
    df = df.sort_values(['wholesaler', 'product'])
    
    #             wholesaler product  sales    avg_sales_last52weeks
    # date                                                          
    # 2013-12-31       11209   UME24      4                      4.0
    # 2012-12-31       13131   UPE55      1                      1.0
    # 2013-02-23       13131   UPE55   1156                    578.5
    # 2013-04-24       13131   UPE55      1                    386.0
    # 2013-12-18       52237   UPE54      9                      9.0
    # 2013-12-31       52237   UPE54      1                      5.0
    # 2013-12-19       53929   UME24      1                      1.0
    # 2012-12-31       53929   UPE54      4                      4.0
    # 2013-12-31       82204   UPE55      9                      9.0
    # 2013-12-01       83389   UPE54      9                      9.0
    # 2013-12-17       83389   UPE54      1                      5.0
    

    【讨论】:

    • 非常感谢!棒极了!你认为timedelta() 函数可以更快地工作吗?实际上我需要计算超过 2500 万行,我希望找到最快的方法来找到结果。再次感谢您的优雅代码!
    • 哇!相当的数据集。考虑一个数据库 SQL 解决方案,它使用条件聚合查询在日期上运行 avg 和 index 表。然后导入 pandas df。
    【解决方案2】:

    如果平均值是每周平均值,您不应该将总和(每个批发商的每个产品)除以周数,即 52,而不是在 cnct = pd.concat([expd_gb.iloc [n].mean().shift(1) for n in range(len(expd_gb))])?

    如果您的周数少于 52 周,那么您需要将该产品的总销售额除以该批发商的周数。例如,如果在(2016 年)1 月,您销售了 100 个小部件,2 月销售了 200 个,3 月销售了 400 个,那么截至 4 月 1 日,您的总销售额将为 700 个。1 月有 31 天,2 月有 29 天,3 月有 31 天,所以总天数为 91 天,恰好是 13 周(91/7)。因此,这三个月期间的平均每周销售额将是 700/13 或大约。每周 53.85 个小部件。不管你有 91 条日记录、13 条周记录还是 3 条月记录,周均值都一样。

    要获取天数(以及周数),您可以查看 timedelta 对象。超过 52 周后,您还可以使用 timedelta 计算出 52 周(或 364 天)前的日期,并在读取文件时丢弃该日期之前的任何内容。

    【讨论】:

    • 感谢您的评论!它有点复杂。在第一年,由于每个批发商每个产品的记录少于 52 条,我们可以使用所有记录的平均值,但对于接下来的几年,我们只寻找过去 52 周的平均值。此外,所有产品-批发商组合都没有每周记录,这意味着对于某个产品-批发商,例如我们有 12 条记录,因此平均值应为 sum(12 条记录)/52。其实我认为你的评论是对的,但我不知道如何阻碍逻辑!
    猜你喜欢
    • 1970-01-01
    • 2019-08-18
    • 1970-01-01
    • 2020-11-18
    • 2020-09-09
    • 1970-01-01
    • 1970-01-01
    • 2017-06-10
    • 1970-01-01
    相关资源
    最近更新 更多