【问题标题】:GroupBy on multiple columns and apply moving function based on date columnGroupBy 在多个列上并根据日期列应用移动功能
【发布时间】:2019-07-22 06:12:26
【问题描述】:

假设我有这个数据集:

Store_id    Order_id    Date    Order_value
1   1   01/01/2018  1
1   4   02/01/2018  0
1   5   02/01/2018  2
1   6   02/01/2018  1
1   8   03/01/2018  2
1   9   03/01/2018  NA
2   2   01/01/2018  3
2   3   01/01/2018  2
2   7   02/01/2018  NA
2   10  03/01/2018  1
2   11  03/01/2018  2
2   12  03/01/2018  NA

我想应用一个移动函数(例如移动平均值)来检索每个商店和日期的聚合值。

例如,在移动平均线的情况下(窗口 = 2 和 min_periods=1,NA 不计算在内)我想要以下内容:

Store_id    Date    Orders_value
1   01/01/2018  1
1   02/01/2018  1
1   03/01/2018  1.25
2   01/01/2018  2.5
2   02/01/2018  2.5
2   03/01/2018  1.5

为方便您,计算方式如下:

Store_id    Date    Orders_value
1   01/01/2018  (1)/1
1   02/01/2018  (1+2+0+1)/4
1   03/01/2018  (NA+2+1+2+0)/5
2   01/01/2018  (2+3)/2
2   02/01/2018  (NA+2+3)/3
2   03/01/2018  (NA+2+1+NA)/4

因为我不计入 NA,所以就是这样:

Store_id    Date    Orders_value
1   01/01/2018  (1)/1
1   02/01/2018  (1+2+0+1)/4
1   03/01/2018  (2+1+2+0)/4
2   01/01/2018  (2+3)/2
2   02/01/2018  (2+3)/2
2   03/01/2018  (2+1)/2

它给出了你在上面看到的结果。

如何使用pandas 做到这一点?

举个简单的例子,例如,我希望商店 1 在 03/01/2018 的日期是对该商店在 2018 年 2 月 1 日的所有订单值取平均值,并且03/01/2018(在窗口大小为 2 的情况下)。

因此,这就是我想在 2018 年 3 月 1 日为商店 1 做的事情:

( Orders_value(Order_1_value + Order_2_value + ... + Order_n_value , 03/01/2018) + Orders_value(Order_1_value + Order_2_value + ... + Order_m_value , 02/01/2018) ) / (n + m) =

# n & m in Order_n_value & Order_m_value refers to the number of the order for this day at this store - not at the order id of the particular order

= ( Orders_value(Order_1_value, 03/01/2018) + Orders_value(Order_2_value, 03/01/2018) +  Orders_value(Order_1_value, 02/01/2018) + Orders_value(Order_2_value, 02/01/2018) + Orders_value(Order_3_value, 03/01/2018) ) / (2 + 3)

= ( NA + 2 + 1 + 2 + 0 ) / 5

= ( 2 + 1 + 2 + 0) / 4 # NAs not counted in

= 1.25

类似地,我希望对每个商店的所有日期都执行相同的操作。

正如我所说,我想对自己的移动函数做同样的事情,超出pandas 的移动平均线,所以最好提供一个对任何自定义函数都有效的解决方案。

请记住,我最近提出了一个非常相似的问题 (GroupBy on multiple columns and apply moving function),所以如果您需要一些灵感,可以看看它。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    我无法从您的问题中完全了解您的需求,但如果您正在寻找所有 是一种将自定义函数应用于 pandas 中滚动窗口的简单方法,请尝试以下操作:

    import pandas as pd
    df = pd.DataFrame(data=myData)
    df['newColumnName'] = df['DataColumnName'].rolling(window=2).apply(lambda x: myFunction(x))
    

    【讨论】:

    • 我什至无法弄清楚它有什么不同。你乱七八糟地复制/粘贴了这个问题。您的意思是要平均日期吗?
    • 别人会明白的;谢谢你的时间。
    【解决方案2】:

    知道了!你需要使用time-awarerolling

    df.Date = pd.to_datetime(df.Date, dayfirst=True)
    temp_df = df.set_index('Date').groupby('Store_id')['Order_value'].rolling(
            '2d', min_periods=1).mean().reset_index()
    temp_df.groupby(['Store_id', 'Date']).last()
    
    
                    Order_value
    Store_id    
          Date  
    1   2018-01-01          1.00
        2018-01-02          1.00
        2018-01-03          1.25
    2   
    
        2018-01-01          2.50
        2018-01-02          2.50
        2018-01-03          1.50
    

    您还可以将mean 替换为apply 并使用自定义函数。

    【讨论】:

    • 感谢您的回答。但是,您确定这有效吗?首先,您不会在 2018-01-02 为商店 2 生成值。其次,当我尝试使用 '2d' 作为窗口大小时,我得到了这个:raise ValueError("window must be an integer") ValueError: window must be an integer
    • 再次查看我关于商店 2 的帖子;它不是最终输出的 NA,因此您可能在这里遗漏了一些基本的东西(附注:好的,现在更好了)。是的,它是日期时间类型;但老实说,我没有使用您的确切源代码,但我正在修改上一个问题 (stackoverflow.com/q/54792538/9024698) 中的源代码,以便更加一致。
    • 顺便说一句,删除 .dropna() 也不起作用。我现在在商店 2 和 2018-02-01 的最终输出中获得了 NA。
    • 这就是它不起作用的原因。我的代码是围绕您提供的示例精心设计的。仅当您有 1) 单调排序 2) 日期时间类型索引时,时间感知滚动才有效。如果您以不同的方式执行此操作,您将收到您提到的错误
    • 是的,现在只有你的源代码和上面的数据sn-p,它不起作用。
    猜你喜欢
    • 1970-01-01
    • 2017-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-30
    • 2023-03-15
    • 2019-03-19
    相关资源
    最近更新 更多