Unpivot / Flatten pandas将表转换为一个级别索引

时间:2016-03-24 23:42:13

标签: python pandas pivot unpivot melt

对于分析,我开始使用数据框,看起来像这样(但要大得多):

      ID1        ID2           type       Number
0     IE345      E90              I           38
1     IE345      E92              E           26
2     IE345      E93              E           21
3     IE345      E95              R            9
4     IE346      E94              I           41
7     IE346      BLK              E            1

我想取消以下数据框:

Df1 = pd.pivot_table(loads, values=['Number'], 
                       index = ['ID1', 'ID2'], 
                       columns=['Type'], margins=True, 
                       aggfunc=[sum] , fill_value=0)

DF1:

                               sum                                                    
                       Number                                                             
type                             B     D     E     I    L     R    All                         
ID1        ID2                                                                         
IE345      E90                   0     0     0    38    0     0     38    
           E92                   0     0    26     0    0     0     26    
           E93                   0     0    21     0    0     0     21    
           E95                   0     0     0     0    0     9      9    
IE346      E94                   0     0     0    41    0     0     41    
           BLK                   0     0     1     0    0     0      1  

分为:

Df1:

ID1        ID2                   B     D     E     I    L     R    All                                                                         
IE345      E90                   0     0     0    38    0     0     38    
IE345      E92                   0     0    26     0    0     0     26    
IE345      E93                   0     0    21     0    0     0     21    
IE345      E95                   0     0     0     0    0     9      9    
IE346      E94                   0     0     0    41    0     0     41    
IE346      BLK                   0     0     1     0    0     0      1

pandas.melt似乎正在寻找,但无法使其成功。

之后我想添加一行最高值的列名,但当然没有边距:

ID1        ID2                   B     D     E     I    L     R    All   Max                                                                        
IE345      E90                   0     0     0    38    0     0     38    I    
IE345      E92                   0     0    26     0    0     0     26    E
IE345      E93                   0     0    21     0    6     0     27    E
IE345      E95                   0     0     0     0    0     9      9    R
IE345      E94                   0     0     0    41    0     0     41    I
IE345      BLK                   0     0     1     0    1     0      2    E

对于最大值,我使用了:

df['Max'] = df.idxmax(axis=1, skipna=True)

但不幸的是,这会带来All with it。关于如何以最有效的方式实现目标的任何想法?

!!! EDIT !!!!

对于第一部分,我构建了一个解决方案,它返回exacte一个unpivot数据透视表!看这里的代码:

df.columns = df.columns.get_level_values('Type')
df.reset_index(inplace=True)

现在我尝试了Vmg的最大值解决方案,但不幸的是它返回:

ValueError: could not convert string to float: 

有关如何解决此问题的任何想法?

2 个答案:

答案 0 :(得分:1)

正如@vmg已经说idxmax会做的那样:

import io
import StringIO     # for Python 2.X
import pandas as pd

data = """\
      id1        id2           type       number
0     IE345      E90              I           38
1     IE345      E92              E           26
2     IE345      E93              E           21
3     IE345      E95              R            9
4     IE346      E94              I           41
7     IE346      BLK              E            1
"""

#loads = pd.read_csv(io.StringIO(data), sep='\s+', index_col=0)  # for Python 3.X
loads = pd.read_csv(StringIO.StringIO(data), sep='\s+', index_col=0)  # for Python 2.X

# **** interesting part starts here ****

# save all unique types, we will use it later
types = loads.type.unique()

df = pd.pivot_table(loads, values=['number'], 
                       index = ['id1', 'id2'], 
                       columns=['type'], margins=True, 
                       aggfunc='sum', fill_value=0) \
       .reset_index()

# reset column names
df.columns = [c[1] if c[1] else c[0] for c in df.columns.tolist()]

df['max'] = df[types].idxmax(axis=1)

输出:

In [266]: df
Out[266]:
     id1  id2     E     I    R    All max
0  IE345  E90   0.0  38.0  0.0   38.0   I
1  IE345  E92  26.0   0.0  0.0   26.0   E
2  IE345  E93  21.0   0.0  0.0   21.0   E
3  IE345  E95   0.0   0.0  9.0    9.0   R
4  IE346  BLK   1.0   0.0  0.0    1.0   E
5  IE346  E94   0.0  41.0  0.0   41.0   I
6    All       48.0  79.0  9.0  136.0   I

答案 1 :(得分:0)

您描述的第一个转换似乎没有必要,因为您似乎仍希望ID1ID2成为索引。第一个表示是pandas如何显示多个索引,而不重复第二个索引。

您手头的问题,无法全部应用​​idxmax可以通过以下方式实现:

proef['Dominant'] = proef.iloc[:,:-1].idxmax(axis=1, skipna=True)

其中iloc[:,:-1]只是意味着您忽视了最右边的列。