【问题标题】:Pandas: vectorization of Conditional Cumulative SumPandas:条件累积和的向量化
【发布时间】:2016-11-21 17:01:03
【问题描述】:

我正在尝试对 pandas 中的 for 循环进行矢量化以提高性能。我有一个数据集,包括用户、产品、每项服务的日期以及提供的天数。给定以下数据子集:

testdf = pd.DataFrame(data={"USERID": ["A"] * 6,
                            "PRODUCTID": [1] * 6,
                            "SERVICEDATE": [datetime(2016, 1, 1), datetime(
                                2016, 2, 5),
                             datetime(2016, 2, 28), datetime(2016, 3, 25),
                             datetime(2016, 4, 30), datetime(2016, 5, 30)],
                            "DAYSSUPPLY": [30] * 6})

testdf=testdf.set_index(["USERID", "PRODUCTID"])
testdf["datediff"] = testdf["SERVICEDATE"].diff()
testdf.loc[testdf["datediff"].notnull(), "datediff"] = testdf.loc[
    testdf["datediff"].notnull(), "datediff"].apply(lambda x: x.days)
testdf["datediff"] = testdf["datediff"].fillna(0)
testdf["datediff"] = pd.to_numeric(testdf["datediff"])
testdf["over_under"] = testdf["DAYSSUPPLY"].shift() - testdf["datediff"]

我想得到以下结果:

                  DAYSSUPPLY SERVICEDATE  datediff  over_under  desired
USERID PRODUCTID                                                       
A      1                  30  2016-01-01         0         NaN        0
       1                  30  2016-02-05        35        -5.0        0
       1                  30  2016-02-28        23         7.0        7
       1                  30  2016-03-25        26         4.0       11
       1                  30  2016-04-30        36        -6.0        5
       1                  30  2016-05-30        30         0.0        5

本质上,我希望我想要的列是 over_under 的运行总和,但只有在前一行的期望值大于 0 时才对负值求和。期望值永远不会低于 0。一个快速而肮脏的循环在 [user, product] 组上看起来像这样:

running_total = 0
desired_loop = []
for row in testdf.itertuples():
    over_under=row[4]
    # skip first row
    if pd.isnull(over_under):
        desired_loop.append(0)
        continue
    running_total += over_under
    running_total = max(running_total, 0)
    desired_loop.append(running_total)
testdf["desired_loop"] = desired_loop

                  desired_loop
USERID PRODUCTID              
A      1                   0.0
       1                   0.0
       1                   7.0
       1                  11.0
       1                   5.0
       1                   5.0

我对矢量化、pandas 和一般知识还是很陌生。我已经能够对这个 df 中的所有其他计算进行矢量化,但是这种累积和的特殊情况我只是不知道如何去做。

谢谢!

【问题讨论】:

    标签: python pandas vectorization


    【解决方案1】:

    我遇到了类似的问题,并使用了一些非常规的迭代解决了它。

    testdf["desired"] = testdf["over_under"].cumsum()
    current = np.argmax( testdf["desired"] < 0 )
    while current != 0:
        testdf.loc[current:,"desired"] += testdf["desired"][current] # adjust the cumsum going forward
        # the previous statement also implicitly sets
        # testdf.loc[current, "desired"] = 0
        current = np.argmax( testdf["desired"][current:] < 0 )
    

    本质上,您正在查找所有“事件”并随着时间的推移重新调整正在运行的 cumsum。所有的操作和测试操作都是矢量化的,所以如果你的desired 列不经常交叉否定,你应该很快。

    这绝对是一个 hack,但它为我完成了工作。

    【讨论】:

      猜你喜欢
      • 2019-10-29
      • 2019-10-05
      • 2017-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-28
      • 2021-07-20
      • 1970-01-01
      相关资源
      最近更新 更多