Pandas:更改具有多级列的数据框中的特定列名

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/40459254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 02:22:40  来源:igfitidea点击:

Pandas: Change a specific column name in dataframe having multilevel columns

pythonpandasdataframemulti-level

提问by sh.jeon

I want to find the way change name of specific column in a multilevel dataframe.

我想找到在多级数据框中更改特定列名称的方法。

With this data:

有了这个数据:

data = {
    ('A', '1', 'I'): [1, 2, 3, 4, 5], 
    ('B', '2', 'II'): [1, 2, 3, 4, 5], 
    ('C', '3', 'I'): [1, 2, 3, 4, 5], 
    ('D', '4', 'II'): [1, 2, 3, 4, 5], 
    ('E', '5', 'III'): [1, 2, 3, 4, 5], 
}

dataDF = pd.DataFrame(data)

This code not working:

此代码不起作用:

dataDF.rename(columns = {('A', '1', 'I'):('Z', '100', 'Z')}, inplace=True)

Result:

结果:

    A   B   C   D   E
    1   2   3   4   5
    I   II  I   II  III
0   1   1   1   1   1
1   2   2   2   2   2
2   3   3   3   3   3
3   4   4   4   4   4
4   5   5   5   5   5

And also not:

也不是:

dataDF.columns.values[0] = ('Z', '100', 'Z')

Result:

结果:

    A   B   C   D   E
    1   2   3   4   5
    I   II  I   II  III
0   1   1   1   1   1
1   2   2   2   2   2
2   3   3   3   3   3
3   4   4   4   4   4
4   5   5   5   5   5

But with combination of above codes working!!!

但是结合上述代码可以工作!!!

dataDF.columns.values[0] = ('Z', '100', 'Z')
dataDF.rename(columns = {('A', '1', 'I'):('Z', '100', 'Z')}, inplace=True)
dataDF

Result:

结果:

    Z   B   C   D   E
    100 2   3   4   5
    Z   II  I   II  III
0   1   1   1   1   1
1   2   2   2   2   2
2   3   3   3   3   3
3   4   4   4   4   4
4   5   5   5   5   5

Is this bug of Pandas?

这是Pandas的错误​​吗?

回答by piRSquared

This is my theory

这是我的理论

pandas does not want pd.Indexs to be mutable. We can see this if we try to change the first element of the index ourselves

pandas 不希望pd.Indexs 是可变的。如果我们尝试自己更改索引的第一个元素,我们可以看到这一点

dataDF.columns[0] = ('Z', '100', 'Z')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-32-2c0b76762235> in <module>()
----> 1 dataDF.columns[0] = ('Z', '100', 'Z')

//anaconda/envs/3.5/lib/python3.5/site-packages/pandas/indexes/base.py in __setitem__(self, key, value)
   1372 
   1373     def __setitem__(self, key, value):
-> 1374         raise TypeError("Index does not support mutable operations")
   1375 
   1376     def __getitem__(self, key):

TypeError: Index does not support mutable operations
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-32-2c0b76762235> in <module>()
----> 1 dataDF.columns[0] = ('Z', '100', 'Z')

//anaconda/envs/3.5/lib/python3.5/site-packages/pandas/indexes/base.py in __setitem__(self, key, value)
   1372 
   1373     def __setitem__(self, key, value):
-> 1374         raise TypeError("Index does not support mutable operations")
   1375 
   1376     def __getitem__(self, key):

TypeError: Index does not support mutable operations


But pandas can't control what you do the valuesattribute.

但是pandas无法控制你做什么values属性。

dataDF.columns.values[0] = ('Z', '100', 'Z')

we see that dataDF.columnslooks the same, but dataDF.columns.valuesclearly reflects the change. Unfortunately, df.columns.valuesisn't what shows up on the display of the dataframe.

我们看到dataDF.columns看起来一样,但dataDF.columns.values清楚地反映了变化。不幸的是,df.columns.values这不是数据框显示中显示的内容。



On the other hand, this really does seem like it should work. The fact that it doesn't feels wrong to me.

另一方面,这似乎确实应该起作用。事实上,它对我来说并没有错。

dataDF.rename(columns={('A', '1', 'I'): ('Z', '100', 'Z')}, inplace=True)

I believe the reason this only works after having changed the values, is that renameis forcing the reconstruction of the columns by looking at the values. Since we change the values, it now works. This is exceptionally kludgy and I don't recommend building a process that relies on this.

我相信这仅在更改值后才有效的原因rename是通过查看值强制重建列。由于我们更改了值,它现在可以工作了。这非常笨拙,我不建议构建依赖于此的流程。



my recommendation

我的建议

  • identify location of column name you want to change
  • assign name of column to the array of values
  • build new columns from scratch, explicity
  • 确定要更改的列名的位置
  • 将列名分配给值数组
  • 明确地从头开始构建新列


from_col = ('A', '1', 'I')
to_col = ('Z', '100', 'Z')
colloc = dataDF.columns.get_loc(from_col)
cvals = dataDF.columns.values
cvals[colloc] = to_col

dataDF.columns = pd.MultiIndex.from_tuples(cvals.tolist())

dataDF

[![enter code here][1]][1]

回答by Dark Matter

You can simply change it like DF.columns.levels=[[u'Z', u'B', u'C', u'D', u'E'],[u'5', u'2', u'3', u'4', u'5'],[u'IIIIII', u'II', u'III']]

你可以简单地改变它 DF.columns.levels=[[u'Z', u'B', u'C', u'D', u'E'],[u'5', u'2', u'3', u'4', u'5'],[u'IIIIII', u'II', u'III']]

回答by novastar

I came across this question as I was myself trying to find the solution for renaming the column names in a data frame with multiple levels. I tried the solution provided by @Dark Matter since it appeared to be very simple solution:

我遇到了这个问题,因为我自己试图找到在具有多个级别的数据框中重命名列名的解决方案。我尝试了@Dark Matter 提供的解决方案,因为它看起来非常简单:

dataDF.columns.levels = [[u'Z', u'B', u'C', u'D', u'E'], [u'100', u'2', u'3', u'4', u'5'], [u'Z', u'II', u'III']]

But an error message was displayed:

但是显示了一条错误消息:

C:\anaconda3\lib\site-packages\ipykernel_launcher.py:1: FutureWarning: setting `levels` directly is deprecated. Use set_levels instead
  """Entry point for launching an IPython kernel.

It appears that it worked but does not work anymore. So I used:

看起来它有效但不再有效。所以我使用了:

dataDF.columns.set_levels([['Z', 'B', 'C', 'D', 'E'],
                           ['100', '2', '3', '4', '5'],
                           ['Z', 'II', 'III']],
                          [0, 1, 2], inplace=True)

Result: dataDF

结果: dataDF

Z   B   C   D   E
100 2   3   4   5
Z   II  Z   II  III
0   1   1   1   1   1
1   2   2   2   2   2
2   3   3   3   3   3
3   4   4   4   4   4
4   5   5   5   5   5