【问题标题】:Unpivot/Flatten pandas pivot table into one level indexUnpivot/Flatten pandas 数据透视表到一级索引
【发布时间】:2016-07-12 17:32:51
【问题描述】:

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

      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)

但不幸的是,这需要全部。关于如何以最有效的方式实现目标的任何想法?

!!!编辑!!!!

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

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

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

ValueError: could not convert string to float: 

关于如何解决这个问题的任何想法?

【问题讨论】:

    标签: python pandas pivot unpivot melt


    【解决方案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
    

    【讨论】:

    • 很好的解决方案,列中的唯一值!很聪明!但是,它还不起作用。类型返回: ['I' 'R' 'E' 'F' 'Y' 'G'] 所以我得到错误: KeyError: "['I' 'R' 'E' 'F' 'Y' ' G'] 不在索引中"
    • @Uis234,尝试完全执行我的脚本 - 是否通过异常?
    • 我试过了: types = np.unique(df[['Type']]), types = pd.unique(df.ravel()) , types = df['Type'].unique ()。全部返回列名,不以“,”分隔
    • 嗨 MaxU,我尝试在我的代码中完全执行您的代码,但加载 = pd.read_csv(io.StringIO(data), sep='\s+', index_col=0) 没有执行而且由于我不知道这是如何工作的,所以我不知道如何解决它:(
    • @Uis234,请发布来自:df['Type'].unique() 的输出,您希望在之前旋转
    【解决方案2】:

    您描述的第一个转换似乎没有必要,因为您似乎仍然希望 ID1ID2 成为索引。第一个表示只是 pandas 显示多个索引的方式,而无需为第二个中的每个条目重复第一个索引。

    您手头的问题,可以通过以下方式应用idxmax 来解决:

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

    iloc[:,:-1] 仅表示您忽略了最右边的列。

    【讨论】:

    • 您好 Vmg,感谢您的回答!我的初始数据框当然与上面的数据透视表不同。否则就不需要转型了。我将使用初始数据框更新问题,因为我需要我在开始时所做的转换,并希望看到它转换回来,如图所示。
    猜你喜欢
    • 1970-01-01
    • 2016-09-15
    • 1970-01-01
    • 2020-08-30
    • 1970-01-01
    • 2017-05-24
    • 1970-01-01
    • 1970-01-01
    • 2020-10-17
    相关资源
    最近更新 更多