首页 > 解决方案 > 如何对数据框进行困难的计算

问题描述

样本数据

df = pd.DataFrame({'sales': ['2020-01','2020-02','2020-03','2020-04','2020-05','2020-06'],
                   '2020-01': [24,42,18,68,24,30,11],
                   '2020-02': [24,42,18,68,24,30,12],
                   '2020-03': [64,24,70,70,88,57,13],
                   '2020-04': [22,11,44,3,5,78,14],
                   '2020-05': [11,35,74,12,69,51]}
print(df)
     sales  2020-01  2020-02  2020-03  2020-04  2020-05
0  2020-01       24       24       64       22       11
1  2020-02       42       42       24       11       35
2  2020-03       18       18       70       44       74
3  2020-04       68       68       70        3       12
4  2020-05       24       24       88        5       69
5  2020-06       30       30       57       78       51

我的代码和公式

要获得 L3,我的代码如下(L3:过去 3 个月表的总和)


Values = df.values[:, 1:]
L3 = []
RANGE = Values.shape[0]

for a in range(RANGE):
    if a == 0:
        result = Values[a,a]
    else:
        if a < 3:
            result = np.sum(Values[0:a+1,0:a+1])
        else:
            result = np.sum(Values[a-2:a+1,a-2:a+1])
    L3.append(result)

df["L3"] = L3

print(df)
     sales  2020-01  2020-02  2020-03  2020-04  2020-05  2020-06   L3
0  2020-01       24       24       64       22       11       64   24
1  2020-02       42       42       24       11       35       24  132
2  2020-03       18       18       70       44       74       70  326
3  2020-04       68       68       70        3       12       70  350
4  2020-05       24       24       88        5       69       88  435
5  2020-06       30       30       57       78       51       57  433

L3(2020-01) = 24
--------------------
     sales  2020-01
0  2020-01       24
--------------------

L3(2020-02) = 132 (sum of 2x2 matrix)
--------------------
     sales  2020-01  2020-02
0  2020-01       24       24
1  2020-02       42       42
--------------------

L3(2020-03) = 326 (sum of 3x3 matrix)
--------------------
     sales  2020-01  2020-02  2020-03
0  2020-01       24       24       64
1  2020-02       42       42       24
2  2020-03       18       18       70
--------------------
L3(2020-04) = 350 (sum of 3x3 matrix)
--------------------
     sales  2020-02  2020-03  2020-04
0  2020-02       42       24       11
1  2020-03       18       70       44
2  2020-04       68       70        3
--------------------

问题

有时数据框很脏。

(按月对原始数据进行排序后,我用 pandas 交叉表创建了一个数据框。如果几个月没有数据,则行和列会扭曲,如下所示。)

如何在数据框下方获得“L3”?

example,
df = pd.DataFrame({'sales': ['2019-12','2020-01','2020-02','2020-03','2020-04','2020-05','2020-06'],
                   '2020-01': [0,24,42,18,68,24,30],
                   '2020-02': [6,24,42,18,68,24,30],
                   '2020-03': [7,64,24,70,70,88,57],
                   '2020-05': [13,11,35,74,12,69,51],
                   '2020-06': [14,64,24,70,70,88,57]})

     sales  2020-01  2020-02  2020-03  2020-05  2020-06
0  2019-12        0        6        7       13       14
1  2020-01       24       24       64       11       64
2  2020-02       42       42       24       35       24
3  2020-03       18       18       70       74       70
4  2020-04       68       68       70       12       70
5  2020-05       24       24       88       69       88
6  2020-06       30       30       57       51       57

预期产出


     sales  2020-01  2020-02  2020-03  2020-05  2020-06   L3
0  2019-12        0        6        7       13       14    0
1  2020-01       24       24       64       11       64   24
2  2020-02       42       42       24       35       24  138
3  2020-03       18       18       70       74       70  326
4  2020-04       68       68       70       12       70  292
5  2020-05       24       24       88       69       88  383
6  2020-06       30       30       57       51       57  347

标签: pythonpandasdataframecrosstab

解决方案


您可以使用.reindex使数据框的形状等于宽度/高度,然后进行计算:

from itertools import count


# make the shape of dataframe equal:
df = df.set_index("sales")
if len(df.index) > len(df.columns):
    df = df.reindex(df.index, axis=1, fill_value=0)
else:
    df = df.reindex(df.columns, axis=0, fill_value=0)

# do the computation:
c = count(1)
df["L3"] = df.apply(
    lambda x: df.iloc[max(0, (cnt := next(c)) - 3) : cnt, max(0, cnt - 3) : cnt]
    .sum()
    .sum(),
    axis=1,
)

print(df)

印刷:

sales    2019-12  2020-01  2020-02  2020-03  2020-04  2020-05  2020-06   L3
sales                                                                      
2019-12        0        0        6        7        0       13       14    0
2020-01        0       24       24       64        0       11       64   24
2020-02        0       42       42       24        0       35       24  138
2020-03        0       18       18       70        0       74       70  326
2020-04        0       68       68       70        0       12       70  292
2020-05        0       24       24       88        0       69       88  383
2020-06        0       30       30       57        0       51       57  347

推荐阅读