Pandas 从长到宽的子集

Pandas long to wide by subsets

我有以下格式的数据框

YR    WEEK  ACCOUNT   Tax   AMOUNT   SURCHARGE  Label
2021   1      1       10     5000     5          0
2021   1      2       20     10000    10         1
2021   2      1       20     2000      2         0
2021   2      2        5      10       3         1
2021   3      1       20     10000    10         1
2021   3      2       10     40000    50         1

我想重塑它,结果如下

ACCOUNT    YR    WEEK    Tax_1   Amount_1   Surcharge_1    Tax_2   Amount_2   Surcharge_2   Label
1         2021    2      10       5000         5             20     2000        2           0
2         2021    2      20       10000       10             5      10          3           1
1         2021    3      0         2000        2             20     10000       10          1
2         2021    3      5          10       3              10     40000        50          1

每一行都是 reshaped,因此它是过去 2 行(按帐户、年份和周)的函数。 LabelWEEK 的当前标签 我先尝试 reshapewide

df.pivot('ACCOUNT', columns=['YR','WEEK'])

并打算在 reshape 之后尝试,但是 pivot 产生了 NaN 值 关于如何在 pandas 中实现此目标的任何想法 谢谢!

你想要的不是 pivot,因为 pivot 重塑了数据,而你在这里想要 duplicate/shift 它(你之后比之前有更多的数据单元格)。

举一个更简单的例子,目标是从这样的事情开始(6 个值):

   id  group value
0   1      1     A
1   1      2     B
2   1      3     C
3   2      1     D
4   2      2     E
5   2      3     F

对此(8 个值):

   id  group_1 value_1  group_2 value_2
0   1        1       A        2       B
1   1        2       B        3       C
2   2        1       D        2       E
3   2        2       E        3       F

我们怎么做?

您可以通过对每个组进行选择并连接两个输出来实现您想要的效果:

cols = ['YR', 'ACCOUNT']
g = df.sort_values(by=['YR', 'WEEK']).groupby(cols)

out = (
 pd.concat([g.apply(lambda d: d.drop(columns=cols+['WEEK']).iloc[:-1]).droplevel(-1).add_suffix('_1'),
            g.apply(lambda d: d.drop(columns=cols).iloc[1:]).droplevel(-1).add_suffix('_2')
            ], axis=1)
   .reset_index()
)

注意。 labels

的输出略有不同

输出:

     YR  ACCOUNT  Tax_1  AMOUNT_1  SURCHARGE_1  Label_1  WEEK_2  Tax_2  AMOUNT_2  SURCHARGE_2  Label_2
0  2021        1     10      5000            5        0       2     20      2000            2        0
1  2021        1     20      2000            2        0       3     20     10000           10        1
2  2021        2     20     10000           10        1       2      5        10            3        1
3  2021        2      5        10            3        1       3     10     40000           50        1
精简版

注意。这要求没有 NaNs

cols = ['YR', 'ACCOUNT']
g = df.sort_values(by=['YR', 'WEEK']).groupby(cols)
pd.concat([g.shift().add_suffix('_1'), df.add_suffix('_2')], axis=1).dropna(how='any', axis=0)