Pandas 自定义函数

问题描述

我有一个像这样的熊猫数据框:

客户 ID PROD_ID 数量 价格 数量 价格 数量 价格
31-12-2020 31-12-2020 01-01-2021 01-01-2021 02-01-2021 02-01-2021
123 ABC 10 5 10 5.4 11 6
123 efg 50 53 50 53 100 53
456 ABC 10 5 10 5.4 10 6
456 efg 10 53 10 53 11 53

列是双索引的,前两行如下所示(日期+价格/数量)。 我想为每个日期(31-12-20 之后)创建一个计算以下内容的新列:

如果数量与前一天不同,则该行的新列包含 0。 ELSE 新列包含(日期数量 * 日期价格)减去(-)(上一个日期数量 * 上一个日期价格)

我创建了一个 for 循环,但它为每个日期迭代数据框,但花费的时间太长。 如何创建这样的功能来应用? PS 索引可靠,但列顺序可能不同。

解决方法

首先,这是您的数据框的干净版本:

df = pd.DataFrame({('123','abc'): [10,5,10,5.4,11,6],('123','efg'): [50,53,50,100,53],('456',5.9,'efg'): [10,53]},index=pd.MultiIndex.from_product([pd.to_datetime(['31-12-2020','01-01-2021','02-01-2021']),['Quantity','Price']]).swaplevel()
                 ).T

数据:

          Quantity      Price   Quantity      Price   Quantity      Price
        2020-12-31 2020-12-31 2021-01-01 2021-01-01 2021-02-01 2021-02-01
123 abc       10.0        5.0       10.0        5.4       11.0        6.0
    efg       50.0       53.0       50.0       53.0      100.0       53.0
456 abc       10.0        5.9       10.0        5.4       10.0        6.0
    efg       10.0       53.0       10.0       53.0       11.0       53.0

然后您可以移动列并计算差异:

(df-df.shift(2,axis=1)).rename(mapper=lambda x: f'{x}_diff',axis='columns',level=0).dropna(axis=1)

输出:

        Quantity_diff Price_diff Quantity_diff Price_diff
           2021-01-01 2021-01-01    2021-02-01 2021-02-01
123 abc           0.0        0.4           1.0        0.6
    efg           0.0        0.0          50.0        0.0
456 abc           0.0       -0.5           0.0        0.6
    efg           0.0        0.0           1.0        0.0

组合数据框:

pd.concat([df,(df-df.shift(2,level=0).dropna(axis=1)
           ],axis=1).sort_index(level=[1,0],ascending=[True,False],axis=1)

输出:

          Quantity      Price Quantity_diff   Quantity Price_diff      Price Quantity_diff   Quantity Price_diff      Price
        2020-12-31 2020-12-31    2021-01-01 2021-01-01 2021-01-01 2021-01-01    2021-02-01 2021-02-01 2021-02-01 2021-02-01
123 abc       10.0        5.0           0.0       10.0        0.4        5.4           1.0       11.0        0.6        6.0
    efg       50.0       53.0           0.0       50.0        0.0       53.0          50.0      100.0        0.0       53.0
456 abc       10.0        5.9           0.0       10.0       -0.5        5.4           0.0       10.0        0.6        6.0
    efg       10.0       53.0           0.0       10.0        0.0       53.0           1.0       11.0        0.0       53.0