为分类列中的分类值创建行

时间:2017-03-13 21:09:36

标签: python pandas seaborn

这是我在StackOverflow的第一个问题。我希望你可以帮助解决一段时间困扰我的问题。我无法找到合适的答案。

我的数据如下:

df = pd.DataFrame({'col1': {0: 1, 1: 1, 2: 1},
               'col2': {0: 1, 1: 2, 2: 3},
               'col3': {0: 1, 1: 2, 2: 3},
               'col4': {0: 1.1, 1: 2.1, 2: 3.1},
               'col5': {0: 10, 1: 12, 2: 14},
               'col6': {0: 1.2, 1: 2.2, 2: 3.2},
               'col7': {0: 11, 1: 13, 2: 15},
              })
df.columns = ["VZ", "NZ", "L", "T_0_Rel", "T_0_Abs", "T_Akt_Rel", "T_Akt_Abs"]
df

输出(没有索引列):

╔════╦════╦═══╦═════════╦═════════╦═══════════╦═══════════╗
║ VZ ║ NZ ║ L ║ T_0_Rel ║ T_0_Abs ║ T_Akt_Rel ║ T_Akt_Abs ║
╠════╬════╬═══╬═════════╬═════════╬═══════════╬═══════════╣
║  1 ║  1 ║ 1 ║   1.1   ║    10   ║    1.2    ║     11    ║
║  1 ║  1 ║ 2 ║   2.1   ║    12   ║    2.2    ║     13    ║
║  1 ║  1 ║ 3 ║   3.1   ║    14   ║    3.2    ║     15    ║
╚════╩════╩═══╩═════════╩═════════╩═══════════╩═══════════╝

现在我想把这个DataFrame扭曲成这样的东西:

╔════╦════╦═══╦═════════════╦═════╦═════╗
║ VZ ║ NZ ║ L ║ T_0 / T_Akt ║ Abs ║ Rel ║
╠════╬════╬═══╬═════════════╬═════╬═════╣
║  1 ║  1 ║ 1 ║     T_0     ║ 10  ║ 1.1 ║
║  1 ║  1 ║ 1 ║     T_Akt   ║ 11  ║ 1.2 ║
║  1 ║  2 ║ 2 ║     T_0     ║ 12  ║ 2.1 ║
║  1 ║  2 ║ 2 ║     T_Akt   ║ 13  ║ 2.2 ║
║  1 ║  3 ║ 3 ║     T_0     ║ 14  ║ 3.1 ║
║  1 ║  3 ║ 3 ║     T_Akt   ║ 15  ║ 3.2 ║
╚════╩════╩═══╩═════════════╩═════╩═════╝

基本上,我希望每个T_O-和T_Akt值都有一行,而Abs-和Rel-值可以保持在一行。

我认为这应该可以通过 .stack() .melt()来实现,但我可以弄明白该怎么做。

我在这一切背后的意图是在我的DataFrame中使用色调 - 参数 seaborn.boxplot .violinplot 功能。我无法弄清楚如何将hue-argument与几列而不是分类值一起使用。 (也许我在这里错了,有一种更简单的方法......)

非常感谢。

1 个答案:

答案 0 :(得分:4)

由于您在概念上有一个分层列索引,我会这样做,然后使用stack

df = pandas.DataFrame({
    'VZ': {0: 1, 1: 1, 2: 1},
    'NZ': {0: 1, 1: 2, 2: 3},
    'L': {0: 1, 1: 2, 2: 3},
    'T_0_Rel': {0: 1.1, 1: 2.1, 2: 3.1},
    'T_0_Abs': {0: 10, 1: 12, 2: 14},
    'T_Akt_Rel': {0: 1.2, 1: 2.2, 2: 3.2},
    'T_Akt_Abs': {0: 11, 1: 13, 2: 15},
})

print(
    df.set_index(['VZ', 'NZ', 'L'])  # row labels
      .rename(columns=lambda c: tuple(c.rsplit('_', 1)))  # create the multi-cols
      .stack(level=0) # unpivot
      .reset_index()  # move the row labels back into normal columns 
)

我明白了:

   VZ  NZ  L level_3  Abs  Rel
0   1   1  1     T_0   10  1.1
1   1   1  1   T_Akt   11  1.2
2   1   2  2     T_0   12  2.1
3   1   2  2   T_Akt   13  2.2
4   1   3  3     T_0   14  3.1
5   1   3  3   T_Akt   15  3.2
相关问题