重命名具有任意顺序和重复列名的多索引列
Posted
技术标签:
【中文标题】重命名具有任意顺序和重复列名的多索引列【英文标题】: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 似乎工作正常。我想知道是否有更“熊猫原生”的解决方案,但现在它可以解决问题!
我不知道熊猫内置的更好方法,但很高兴我能提供帮助!
【参考方案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
。以上是关于重命名具有任意顺序和重复列名的多索引列的主要内容,如果未能解决你的问题,请参考以下文章