【问题标题】:Pandas: Sort multilevel column with mixed datatypesPandas:使用混合数据类型对多级列进行排序
【发布时间】:2021-02-15 19:41:01
【问题描述】:

这是我的previous 问题的扩展。

下面是df:

In [28]: df = pd.DataFrame({'A':['a','b:all:c','all:1:3','c','d','e'], 'D':[{"value": '126', "perc": None, "unit": None}, {"value": 324, "perc": None, "unit": None}, {"value": 'N/A', "perc": None, "unit": None}, {}, {"value": '100', "perc": None, "unit":
    ...:  None}, np.nan]})
    ...: 
In [34]: df.columns = pd.MultiIndex.from_product([df.columns, ['E']])

In [35]: df
Out[35]: 
         A                                             D
         E                                             E
0        a  {'value': '126', 'perc': None, 'unit': None}
1  b:all:c    {'value': 324, 'perc': None, 'unit': None}
2  all:1:3  {'value': 'N/A', 'perc': None, 'unit': None}
3        c                                            {}
4        d  {'value': '100', 'perc': None, 'unit': None}
5        e                                           NaN

我需要根据dict中的值键对索引为(D,E)的多级列进行降序排序。

但我需要保留所有先前列中包含子字符串 all 的行。

如您所见,值键可以具有混合数据类型的值,如 int、string 或空(如 {} 或 NaN)。

N/A 和 Nan 值应始终在排序后出现(包括 asc 和 desc)。

因此,预期的输出将是:

In [38]: df1 = pd.DataFrame({'A':['a','b:all:c','all:1:3','d','c','e'], 'D':[{"value": '126', "perc": None, "unit": None}, {"value": 324, "perc": None, "unit": None}, {"value": 'N/A', "perc": None, "unit": None}, {"value": '100', "perc": None, "unit": No
    ...: ne},{}, np.nan]})
    ...: 

In [40]: df1.columns = pd.MultiIndex.from_product([df1.columns, ['E']])

In [41]: df1
Out[41]: 
         A                                             D
         E                                             E
0        a  {'value': '126', 'perc': None, 'unit': None}
1  b:all:c    {'value': 324, 'perc': None, 'unit': None}
2  all:1:3  {'value': 'N/A', 'perc': None, 'unit': None}
3        d  {'value': '100', 'perc': None, 'unit': None}
4        c                                            {}
5        e                                           NaN

【问题讨论】:

    标签: python python-3.x pandas dataframe sorting


    【解决方案1】:

    想法是首先在(D, E)列之前找到所有带有all的行进行屏蔽,然后将不匹配的行过滤到df1,排序并提取用于映射原始索引值和最后排序的索引值:

    print (df)
    mask = (df.iloc[:, : df.columns.get_loc(('D','E'))]
              .apply(lambda x: x.astype(str).str.contains('all'))
              .any(axis=1))
    print (mask)
    0    False
    1     True
    2     True
    3    False
    4    False
    5    False
    dtype: bool
    
    df1 = df[~mask].copy()
    df1['tmp'] = pd.to_numeric(df1[('D','E')].str.get('value'), errors='coerce')
    idx = df1.sort_values('tmp', ascending=False).index
    print (idx)
    Int64Index([0, 4, 3, 5], dtype='int64')
    
    d = dict(zip(df.index[~mask], idx))
    print (d)
    {0: 0, 3: 4, 4: 3, 5: 5}
    
    df = df.set_index(df.rename(d).index).sort_index()
    print (df)
             A                                             D
             E                                             E
    0        a  {'value': '126', 'perc': None, 'unit': None}
    1  b:all:c    {'value': 324, 'perc': None, 'unit': None}
    2  all:1:3  {'value': 'N/A', 'perc': None, 'unit': None
    3        d  {'value': '100', 'perc': None, 'unit': None}
    4        c                                            {}
    5        e                                           NaN
    

    【讨论】:

    • 感谢您的解决方案。即使有更多带有all 子字符串的列,此解决方案是否有效?在这种情况下,我们需要避免所有列中包含all 作为子字符串的行。
    • @MayankPorwal - 所以如果所有行都有all 那么没有排序,对吧?因为只对非all 行进行排序,对吧?
    • 是的。让我添加示例数据以进行更多说明。
    • 不需要样本数据。我检查过,您的解决方案也适用于其他情况。
    • @MayankPorwal - 抱歉,我忘记了 ;) OOP,
    猜你喜欢
    • 2021-02-10
    • 1970-01-01
    • 2012-11-07
    • 2018-03-15
    • 2013-08-22
    • 2018-10-17
    • 2020-02-29
    • 1970-01-01
    • 2020-11-05
    相关资源
    最近更新 更多