旋转 Pandas Table - 特殊问题

Pivoting a Pandas Table - Peculiar Problem

似乎我有一个旋转 pandas Table 的简单问题,但不幸的是,这个问题对我来说似乎有点复杂。

我提供了一个小样本 table 以及我希望给出的输出,以举例说明我面临的问题:

说,我有一个 table 这样的:

df = 
     AF   BF    AT  BT  
     1    4    100  70
     2    7    102  66
     3   11    200  90
     4   13    300  178
     5   18    403  200

所以我需要把它变成wide/pivot格式,但是每种情况下的参数名称都将设置为相同。 (如果可能的话,我不希望对字符串进行子集化)

我的输出 table 应该如下所示:

    dfout = 

         PAR   F    T
          A    1    100
          B    4    70
          A    2    102
          B    7    66
          A    3    200
          B    11   90
          A    4    300
          B   13    178
          A    5    403
          B   18    200

我试过旋转,但无法获得所需的输出。任何帮助将不胜感激。谢谢

您可以使用 pandas wide_to_long,但首先您必须对列重新排序:

pd.wide_to_long(
    df.rename(columns=lambda x: x[::-1]).reset_index(),
    stubnames=["F", "T"],
    i="index",
    sep="",
    j="PAR",
    suffix=".",
).reset_index("PAR")



     PAR    F   T
index           
0   A   1   100
1   A   2   102
2   A   3   200
3   A   4   300
4   A   5   403
0   B   4   70
1   B   7   66
2   B   11  90
3   B   13  178
4   B   18  200

或者,您可以使用 pivot_longer function from the pyjanitor 来重塑数据:

# pip install pyjanitor
import janitor
df.pivot_longer(names_to=("PAR", ".value"), names_pattern=r"(.)(.)")

   PAR  F   T
0   A   1   100
1   B   4   70
2   A   2   102
3   B   7   66
4   A   3   200
5   B   11  90
6   A   4   300
7   B   13  178
8   A   5   403
9   B   18  200

更新:使用来自@jezrael的数据:

df

    C  AF  BF   AT   BT
0  10   1   4  100   70
1  20   2   7  102   66
2  30   3  11  200   90
3  40   4  13  300  178
4  50   5  18  403  200


pd.wide_to_long(
    df.rename(columns=lambda x: x[::-1]),
    stubnames=["F", "T"],
    i="C",
    sep="",
    j="PAR",
    suffix=".",
).reset_index()

     C  PAR F   T
0   10  A   1   100
1   20  A   2   102
2   30  A   3   200
3   40  A   4   300
4   50  A   5   403
5   10  B   4   70
6   20  B   7   66
7   30  B   11  90
8   40  B   13  178
9   50  B   18  200

如果您使用 pivot_longer 函数:

df.pivot_longer(index="C", names_to=("PAR", ".value"), names_pattern=r"(.)(.)")


    C   PAR F   T
0   10  A   1   100
1   10  B   4   70
2   20  A   2   102
3   20  B   7   66
4   30  A   3   200
5   30  B   11  90
6   40  A   4   300
7   40  B   13  178
8   50  A   5   403
9   50  B   18  200

pivot_longer 正在处理中;在 pyjanitor 的下一个版本中应该会好很多。但是 pd.wide_to_long 可以很容易地解决你的任务。其他答案也可以轻松解决。

让我们试试:

(pd.wide_to_long(df.reset_index(),stubnames=['A','B'],
                i='index',
                j='PAR', sep='', suffix='[FT]')
   .stack().unstack('PAR').reset_index(level=1)
     )

输出:

PAR   level_1   F    T
index                 
0           A   1  100
0           B   4   70
1           A   2  102
1           B   7   66
2           A   3  200
2           B  11   90
3           A   4  300
3           B  13  178
4           A   5  403
4           B  18  200

想法是通过第一个和最后一个字母创建MultiIndex in columns,然后使用DataFrame.stack进行整形,最后在MultiIndex in index中进行一些数据清理:

df.columns= [df.columns.str[-1], df.columns.str[0]]
df = df.stack().reset_index(level=0, drop=True).rename_axis('PAR').reset_index()

print (df)
  PAR   F    T
0   A   1  100
1   B   4   70
2   A   2  102
3   B   7   66
4   A   3  200
5   B  11   90
6   A   4  300
7   B  13  178
8   A   5  403
9   B  18  200

编辑:

print (df)
    C  AF  BF   AT   BT
0  10   1   4  100   70
1  20   2   7  102   66
2  30   3  11  200   90
3  40   4  13  300  178
4  50   5  18  403  200

df = df.set_index('C')
df.columns = pd.MultiIndex.from_arrays([df.columns.str[-1], 
                                        df.columns.str[0]], names=[None,'PAR'])
df = df.stack().reset_index()

print (df)
    C PAR   F    T
0  10   A   1  100
1  10   B   4   70
2  20   A   2  102
3  20   B   7   66
4  30   A   3  200
5  30   B  11   90
6  40   A   4  300
7  40   B  13  178
8  50   A   5  403
9  50   B  18  200