重塑 + 分组依据并重命名 pandas 数据框

Reshape + group by and rename pandas dataframe

我有以下数据框:

  Police Product  PV1  PV2  PV3   PM1   PM2  PM3
0       1      AA   10    8   14   150   145  140
1       2      AB   25    4    7   700   650  620
2       3      AA   13   22    5   120    80   60
3       4      AA   12    6   12   250   170  120
4       5      AB   10   13    5   500   430  350
5       6      BC    7   21   12  1200  1000  900

PV1 是第 1 年的项目 PV,PV2 是第 2 年的项目,.... 我想结合重塑和分组操作+一些重命名的东西来获得下面的 DF :

  Product Item  Year1  Year2  Year3
0      AA   PV     35     36     31
1      AA   PM    520    395    320
2      AB   PV     35     17     12
3      AB   PM   1200   1080    970
4      BC   PV      7     21     12
5      BC   PM   1200   1000    900 

它通过对产品名称的操作进行分组并重塑 DF 以将项目作为列传递,并将每个项目的总和放入新列年中。

我尝试了一些测试但没有成功。 如果您有任何想法,我将不胜感激。

感谢您的帮助

第一个想法是通过 DataFrame.set_index, then extract numeric and non numeric values to MultiIndex and assignback, last reshape by DataFrame.stack and rename columns by DataFrame.add_prefix:

将第一列转换为 MultiIndex
df1 = df.set_index(['Police','Product'])
L = df1.columns.str.extract('(\D+)(\d+)').T.to_numpy().tolist()

df1.columns = pd.MultiIndex.from_arrays(L, names=['Item',None])
df1 = df1.stack(level=0).add_prefix('Year').reset_index()
print (df1)
    Police Product Item  Year1  Year2  Year3
0        1      AA   PM    150    145    140
1        1      AA   PV     10      8     14
2        2      AB   PM    700    650    620
3        2      AB   PV     25      4      7
4        3      AA   PM    120     80     60
5        3      AA   PV     13     22      5
6        4      AA   PM    250    170    120
7        4      AA   PV     12      6     12
8        5      AB   PM    500    430    350
9        5      AB   PV     10     13      5
10       6      BC   PM   1200   1000    900
11       6      BC   PV      7     21     12

或使用wide_to_long:

df1 = (pd.wide_to_long(df, 
                     i=['Police','Product'], 
                     stubnames=['PM', 'PV'], 
                     j='tmp')
       .rename_axis('Item', axis=1)
       .stack()
       .unstack(2)
       .add_prefix('year')
       .rename_axis(None, axis=1)
       .reset_index())
print (df1)
    Police Product Item  year1  year2  year3
0        1      AA   PM    150    145    140
1        1      AA   PV     10      8     14
2        2      AB   PM    700    650    620
3        2      AB   PV     25      4      7
4        3      AA   PM    120     80     60
5        3      AA   PV     13     22      5
6        4      AA   PM    250    170    120
7        4      AA   PV     12      6     12
8        5      AB   PM    500    430    350
9        5      AB   PV     10     13      5
10       6      BC   PM   1200   1000    900
11       6      BC   PV      7     21     12