展平pandas DataFrame

时间:2014-11-03 22:49:33

标签: python pandas

我有一个类似于以下

的数据框
import pandas as pd
df = pd.DataFrame(data={"CommonIdentifier":[1234,1235,1236,1237],
                        "CommonValue":["type1","type2","type1","type1"],
                        "Identifier1":["a","a","b","b"],
                        "Value1":[1,1.5,2,1.3],
                        "Identifier2":["b","b","c","a"],
                         "Value2":[4,2,3.2,1]})
df

 CommonIdentifier CommonValue Identifier1 Identifier2 Value1 Value2
0            1234       type1           a           b    1.0    4.0
1            1235       type2           a           b    1.5    2.0
2            1236       type1           b           c    2.0    3.2
3            1237       type1           b           a    1.3    1.0

我想操纵它,所以形式为

pd.DataFrame(data={"CommonIdentifier":[1234,1235,1236,1237,1234,1235,1236,1237],
                   "CommonValue":["type1","type2","type1","type1","type1","type2","type1","type1"],
                   "IdentifierJoined":["a","a","b","b","b","b","c","a"],
                   "ValueJoined":[1,1.5,2,1.3,4,2,3.2,1]})

    CommonIdentifier    CommonValue IdentifierJoined    ValueJoined
0               1234          type1                a            1.0
1               1235          type2                a            1.5
2               1236          type1                b            2.0
3               1237          type1                b            1.3
4               1234          type1                b            4.0
5               1235          type2                b            2.0
6               1236          type1                c            3.2
7               1237          type1                a            1.0

以上只是代表性的,实际上我有9个标识符/值对。我想知道如何以简洁的方式完成这个任务。我想出了以下内容

num_identifiers = 2
m1 = pd.melt(df,id_vars=['CommonIdentifier'],
             value_vars=['Value1','Value2'])
m2 = pd.melt(df,id_vars=['CommonIdentifier'],
             value_vars=['Identifier1','Identifier2'])
m3 = pd.concat([df[["CommonIdentifier","CommonValue"]]] * num_identifiers)
m3.index = range(len(m3))

pd.concat([m3[["CommonIdentifier","CommonValue"]],
           m2[["value"]].rename(columns={"value":"IdentifierJoined"}),
           m1[["value"]].rename(columns={"value":"ValueJoined"})], axis=1)

实现了这种转变,但感觉相当邋/ / longwinded

2 个答案:

答案 0 :(得分:2)

您可以使用df[[...]]选择所需的列, rename(columns=...)更改列名,然后 pd.concat堆叠子DataFrames:

import pandas as pd

df = pd.DataFrame(data={"CommonIdentifier":[1234,1235,1236,1237],
                        "CommonValue":["type1","type2","type1","type1"],
                        "Identifier1":["a","a","b","b"],
                        "Value1":[1,1.5,2,1.3],
                        "Identifier2":["b","b","c","a"],
                         "Value2":[4,2,3.2,1]})

colgroups = [['CommonIdentifier', 'CommonValue', 'Identifier%d'%i, 'Value%d'%i]
        for i in range(1,3)]

colmap = {'{}{}'.format(col,i):'{}Joined'.format(col) 
          for i in range(1,3) for col in ('Identifier', 'Value')}

result = pd.concat([df[cols].rename(columns=colmap) for cols in colgroups])
print(result)

产量

  CommonIdentifier CommonValue IdentifierJoined ValueJoined
0             1234       type1                a           1
1             1235       type2                a         1.5
2             1236       type1                b           2
3             1237       type1                b         1.3
4             1234       type1                b           4
5             1235       type2                b           2
6             1236       type1                c         3.2
7             1237       type1                a           1

另一个灵感来自HYRY解决方案的选择是隐藏索引中的常用列,然后应用HYRY的stack诀窍:

import pandas as pd
df = pd.DataFrame(data={"CommonIdentifier":[1234,1235,1236,1237],
                        "CommonValue":["type1","type2","type1","type1"],
                        "Identifier1":["a","a","b","b"],
                        "Value1":[1,1.5,2,1.3],
                        "Identifier2":["b","b","c","a"],
                         "Value2":[4,2,3.2,1]})

df = df.set_index(['CommonIdentifier', 'CommonValue'])
df.columns = pd.MultiIndex.from_product([["Identifier", "Value"], range(2)])
df = df.stack()
df.index = df.index.droplevel(-1)
print(df.reset_index())

答案 1 :(得分:1)

以下是使用MultiIndexstack()merge()的方法:

import pandas as pd
df = pd.DataFrame(data={"CommonIdentifier":[1234,1235,1236,1237],
                        "CommonValue":["type1","type2","type1","type1"],
                        "Identifier1":["a","a","b","b"],
                        "Value1":[1,1.5,2,1.3],
                        "Identifier2":["b","b","c","a"],
                         "Value2":[4,2,3.2,1]})

common_columns = ["CommonIdentifier", "CommonValue"]
identifier_columns = ["Identifier1", "Identifier2"]
value_columns = ["Value1", "Value2"]

common_df = df[common_columns]
mix_df = df[identifier_columns + value_columns]
mix_df.columns = pd.MultiIndex.from_product([["Identifier", "Value"], range(len(identifier_columns))])
pd.merge(common_df, mix_df.stack().reset_index(level=1, drop=True),
         left_index=True, right_index=True).reset_index(drop=True)