Pandas: Sort innermost column group-wise based on other multilevel column

↘锁芯ラ 提交于 2021-02-07 19:46:31

问题


Consider below df:

In [3771]: df = pd.DataFrame({'A': ['a'] * 11,
               'B': ['b'] * 11,
               'C': ['C1', 'C1', 'C2','C1', 'C3', 'C3', 'C2', 'C3', 'C3', 'C2', 'C2'],
               'D': ['D1', 'D2', 'D1', 'D3', 'D3', 'D2', 'D4', 'D4', 'D1', 'D2', 'D3'],
               'E': [{'value': '4', 'percentage': None}, {'value': 5, 'percentage': None}, {'value': 12, 'percentage': None}, {'value': 5, 'percentage': None}, {'value': '12', 'percentage': None}, {'value': 'N/A', 'percentage': None}, {}, {'value': 19, 'percentage': None}, {'value': 12, 'percentage': None}, {'value': 11, 'percentage': None}, np.nan],
               'F':[{'value': 72, 'percentage': None}, {'value': 72, 'percentage': None}, {'value': 66, 'percentage': None}, {'value': 62, 'percentage': None}, {'value': 66, 'percentage': None}, {'value': 16,      'percentage': None}, {'value': 67, 'percentage': None}, {'value': 67, 'percentage': None}, {'value': 66, 'percentage': None}, {'value': 54, 'percentage': None}, {'value': 78, 'percentage': None}]})

In [3779]: df
Out[3898]: 
    A  B   C   D                                     E                                  F
0   a  b  C1  D1    {'value': '4', 'percentage': None}  {'value': 72, 'percentage': None}
1   a  b  C1  D2      {'value': 5, 'percentage': None}  {'value': 72, 'percentage': None}
2   a  b  C2  D1     {'value': 12, 'percentage': None}  {'value': 66, 'percentage': None}
3   a  b  C1  D3      {'value': 5, 'percentage': None}  {'value': 62, 'percentage': None}
4   a  b  C3  D3   {'value': '12', 'percentage': None}  {'value': 66, 'percentage': None}
5   a  b  C3  D2  {'value': 'N/A', 'percentage': None}  {'value': 16, 'percentage': None}
6   a  b  C2  D4                                    {}  {'value': 67, 'percentage': None}
7   a  b  C3  D4     {'value': 19, 'percentage': None}  {'value': 67, 'percentage': None}
8   a  b  C3  D1     {'value': 12, 'percentage': None}  {'value': 66, 'percentage': None}
9   a  b  C2  D2     {'value': 11, 'percentage': None}  {'value': 54, 'percentage': None}
10  a  b  C2  D3                                   NaN  {'value': 78, 'percentage': None}

I pivot the above df:

In [3776]: x = df.pivot(['B', 'C', 'D'], 'A', ['E', 'F'])

In [3781]: x
Out[3900]: 
                                            E                                  F
A                                           a                                  a
B C  D                                                                          
b C1 D1    {'value': '4', 'percentage': None}  {'value': 72, 'percentage': None}
     D2      {'value': 5, 'percentage': None}  {'value': 72, 'percentage': None}
     D3      {'value': 5, 'percentage': None}  {'value': 62, 'percentage': None}
  C2 D1     {'value': 12, 'percentage': None}  {'value': 66, 'percentage': None}
     D2     {'value': 11, 'percentage': None}  {'value': 54, 'percentage': None}
     D3                                   NaN  {'value': 78, 'percentage': None}
     D4                                    {}  {'value': 67, 'percentage': None}
  C3 D1     {'value': 12, 'percentage': None}  {'value': 66, 'percentage': None}
     D2  {'value': 'N/A', 'percentage': None}  {'value': 16, 'percentage': None}
     D3   {'value': '12', 'percentage': None}  {'value': 66, 'percentage': None}
     D4     {'value': 19, 'percentage': None}  {'value': 67, 'percentage': None}

I want to sort the innermost column which is D for each group of outer columns B and C based on the multi-level column with index (E, a) in descending order based on value key from dict.

EDIT:

The dict can have value key with mixed datatypes. It can be int, str, NaN or simply unavailable.

Expected Output:

                                            E                                  F
A                                           a                                  a
B C  D                                                                          
b C1 D2      {'value': 5, 'percentage': None}  {'value': 72, 'percentage': None}
     D3      {'value': 5, 'percentage': None}  {'value': 62, 'percentage': None}
     D1    {'value': '4', 'percentage': None}  {'value': 72, 'percentage': None}
  C2 D1     {'value': 12, 'percentage': None}  {'value': 66, 'percentage': None}
     D2     {'value': 11, 'percentage': None}  {'value': 54, 'percentage': None}
     D4                                    {}  {'value': 67, 'percentage': None}
     D3                                   NaN  {'value': 78, 'percentage': None}
  C3 D4     {'value': 19, 'percentage': None}  {'value': 67, 'percentage': None}
     D1     {'value': 12, 'percentage': None}  {'value': 66, 'percentage': None}
     D3   {'value': '12', 'percentage': None}  {'value': 66, 'percentage': None}
     D2  {'value': 'N/A', 'percentage': None}  {'value': 16, 'percentage': None}
 


 

回答1:


Solution with helper MultiIndex column created by Series.str.get, then sorting by DataFrame.sort_values and last remove helper column:

x[('new', 'a')] = pd.to_numeric(x[('E','a')].str.get('value'), errors='coerce')
lvl = x.index.names[:-1]

order = 'desc'

x = (x.sort_values(lvl + [('new', 'a')],ascending=[True] * len(lvl) + [order == 'asc'])
       .drop(('new', 'a'), axis=1))

print (x)

                                            E  \
A                                           a   
B C  D                                          
b C1 D2      {'value': 5, 'percentage': None}   
     D3      {'value': 5, 'percentage': None}   
     D1    {'value': '4', 'percentage': None}   
  C2 D1     {'value': 12, 'percentage': None}   
     D2     {'value': 11, 'percentage': None}   
     D3                                   NaN   
     D4                                    {}   
  C3 D4     {'value': 19, 'percentage': None}   
     D1     {'value': 12, 'percentage': None}   
     D3   {'value': '12', 'percentage': None}   
     D2  {'value': 'N/A', 'percentage': None}   

                                         F  
A                                        a  
B C  D                                      
b C1 D2  {'value': 72, 'percentage': None}  
     D3  {'value': 62, 'percentage': None}  
     D1  {'value': 72, 'percentage': None}  
  C2 D1  {'value': 66, 'percentage': None}  
     D2  {'value': 54, 'percentage': None}  
     D3  {'value': 78, 'percentage': None}  
     D4  {'value': 67, 'percentage': None}  
  C3 D4  {'value': 67, 'percentage': None}  
     D1  {'value': 66, 'percentage': None}  
     D3  {'value': 66, 'percentage': None}  
     D2  {'value': 16, 'percentage': None}  


来源:https://stackoverflow.com/questions/65021214/pandas-sort-innermost-column-group-wise-based-on-other-multilevel-column

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!