反透视包含一行中两个团队信息的数据框?

Unpivot a data-frame that has information of two teams in one row?

我有一些数据包含两个对立球队的信息

              home_x           away_x
0                  7               28
1                 11               10
2                 11               20
3                 12               15
4                 12               16

我知道 .melt(),returns 是这样的:

            variable  value
0             home_x      7
1             home_x     11
2             home_x     11
3             home_x     12
4             home_x     12

所以这里每个值都是一行。

每个团队都有几个属性。

我希望每一行都包含相应球队(主场或客场)的所有属性

最终目标是让两队的所有属性都排在同一行。这将使行数加倍。

              home_x           away_x
0                  7               28

将转化为:

             team1_x          team2_x
0                  7               28
0                 28                7

这里有一个方法:

您可能需要对列名称的最后一个拆分进行分组,然后在轴 = 1 上进行分组,然后遍历这些组并反转列顺序并将它们命名为相同的后缀:

def myinfo(data):
    c = data.columns.str.split("_").str[-1]
    f = lambda x: pd.DataFrame.set_axis(x, ["team1","team2"],axis=1)
    l = [pd.concat([*map(f , (v,v.iloc[:,::-1]))]).add_suffix(f"_{k}")
         for k,v in data.groupby(c,axis=1)]
    return pd.concat(l,axis=1).sort_index()

print(myinfo(df))

   team1_x  team2_x
0        7       28
0       28        7
1       11       10
1       10       11
2       11       20
2       20       11
3       12       15
3       15       12
4       12       16
4       16       12

样本 df:

home_x away_x home_y away_y
0 7 28 7 20
1 28 7 28 13
2 28 7 28 4
3 7 28 7 58
4 11 10 11 10

尝试:

res = pd.DataFrame()
for c in df.columns.str.split("_").str[1].unique():
    p1 = df.filter(regex=f"{c}$")
    c1,c2 =p1.columns
    
    df_map = {c1:c2, c2:c1}
    swap = p1.rename(columns={**df_map})
    res = pd.concat([res,p1.append(swap).sort_index(ignore_index=True)], axis=1)

然后重命名列。

import re
repl = {'home': 'team1', 'away': 'team2'}
res.columns = [re.sub('|'.join(repl.keys()), lambda x: repl[x.group()], i) for i in res.columns]

team1_x team2_x team1_y team2_y
0 7 28 7 20
1 28 7 20 7
2 28 7 28 13
3 7 28 13 28
4 28 7 28 4
5 7 28 4 28
6 7 28 7 58
7 28 7 58 7
8 11 10 11 10
9 10 11 10 11