【问题标题】:Renaming multiindex columns with arbitrary order and duplicate column names重命名具有任意顺序和重复列名的多索引列
【发布时间】:2019-01-19 20:07:31
【问题描述】:

我有一个DataFrame overview(这个问题的缩写)。

>>> import pandas as pd
>>> import numpy as np
>>>
>>> index = pd.Index(['Abbott PLC', 'Abbott, Rogahn and Bednar'], dtype='object', name='Account Name')
>>> columns = pd.MultiIndex(levels=[['total', 'quantity'], ['count', 'sum']], labels=[[0, 0, 1], [1, 0, 1]])
>>> values = np.array([[755.44,   1.  ,  19.  ], [615.6 ,   1.  ,  18.  ]])
>>> 
>>> overview = pd.DataFrame(values, columns=columns, index=index)
>>> overview
                            total       quantity
                              sum count      sum
Account Name                                    
Abbott PLC                 755.44   1.0     19.0
Abbott, Rogahn and Bednar  615.60   1.0     18.0

列名很奇怪,因为在我的实际代码中,此结果是从 DataFrame df 派生而来的,具有以下分组操作。

aggregators = {'total': ['sum', 'count'], 'quantity': 'sum'}
overview = df.groupby('Account Name')['total', 'quantity'].agg(aggregators)

我想重命名overview的列,想要的结果是这样的:

                            gross  checkouts  items
Account Name                                       
Abbott PLC                 755.44        1.0   19.0
Abbott, Rogahn and Bednar  615.60        1.0   18.0

我不能简单地使用overview.columns = ['gross', 'checkouts', 'items']this similar question 的答案,因为在使用agg 之后,列的顺序是任意的。 (应用rename 也似乎很棘手,因为重复名称'sum'。)

目前,我正在通过将OrderedDict 用于aggregators 来解决此问题,因此overview 具有确定性的列序数。但是假设 overview 的创建不能在上游修复,我将如何优雅地达到我想要的结果?

【问题讨论】:

  • 如果你扁平化并加入你的列,你会得到像 Index(['total_sum', 'total_count', 'quantity_sum'], dtype='object') 这样的东西,这将是独一无二的,如果我理解正确的话,你可以重命名。跨度>
  • @user3483203 听起来很有希望,请随时写一个答案,教我扁平化和加入过程。
  • 试试overview.columns = ['_'.join(col).strip() for col in overview.columns.values],看看是不是你想走的路,如果是,我会写出来作为答案。
  • @user3483203 似乎工作正常。我想知道是否有更“熊猫原生”的解决方案,但现在它可以解决问题!
  • 我不知道熊猫内置的更好方法,但很高兴我能提供帮助!

标签: python string pandas dataframe indexing


【解决方案1】:

您的数据框有一个 MultiIndex 作为列。有几种方法可以展平为常规索引:

pd.Index.map

overview.columns = overview.columns.map('_'.join)

列表理解 + f-strings

在 Python 3.6+ 中,您可以使用格式化的字符串文字 (PEP 498):

overview.columns = [f'{i}_{j}' for i, j in overview.columns]

列表理解 + str.format / str.join

对于 str.format 或str.join

overview.columns = ['{i}_{j}'.format(i, j) for i, j in overview.columns]

overview.columns = list(map('_'.join, overview.columns))

如果只重命名,可以直接使用字典映射:

d = {('total', 'sum'): 'gross', ('total', 'count'): 'checkouts',
     ('quantity', 'sum'): 'items'}

overview.columns = np.vectorize(d.get)(overview.columns)

【讨论】:

  • 谢谢。我知道如何从临时列名着手。为了完整起见,您可以考虑在答案中包含最终重命名。
  • @timgeb,当然,我还添加了一个更直接的方法,不需要中间重命名。
  • 现在我明白了。容器overview.columns 的工作方式与其打印输出的建议完全不同。实际上,在这种情况下,我可以将其视为元组列表[('total', 'sum'), ('total', 'count'), ('quantity', 'sum')]
  • @timgeb,正是如此。甚至还有一种从元组列表构造Index 的方法:pd.MultiIndex.from_tuples
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-27
  • 1970-01-01
  • 2022-11-21
  • 2012-01-11
  • 1970-01-01
  • 1970-01-01
  • 2020-09-04
相关资源
最近更新 更多