'Pandas- rename dataframe multilevel header according to the name of the first level header

I have a dataframe like this :

    X         Y
    a    b    a    b
0   1    3    4    2
1   5    7    8    6

And I want to rename a specific column name, for example "b" to "b1" under "Y" header. The desired result is

    X         Y
    a    b    a    b1
0   1    3    4    2
1   5    7    8    6

So it is important, that header "b" under "X" remained unchanged. That mean i can't just use rename



Solution 1:[1]

I can not find a function can directly doing this so

df.columns=df.columns.values
df
Out[110]: 
   (X, a)  (X, b)  (Y, a)  (Y, b)
0       1       3       4       2
1       5       7       8       6
df.rename(columns={('Y', 'b'):('Y', 'b1')})
Out[111]: 
   (X, a)  (X, b)  (Y, a)  (Y, b1)
0       1       3       4        2
1       5       7       8        6
df=df.rename(columns={('Y', 'b'):('Y', 'b1')})
df.columns=pd.MultiIndex.from_tuples(df.columns)
df
Out[114]: 
   X     Y   
   a  b  a b1
0  1  3  4  2
1  5  7  8  6

Solution 2:[2]

Alternatively, you could do:

# Find index of column to change.
i = df.columns.get_loc(('Y','b'))
# Rename the column.
cols = df.columns.values
cols[i] = ('Y','b1')
df.columns = pd.MultiIndex.from_tuples(cols)

Still not very convenient.

Solution 3:[3]

Here is a slightly shorter alternative:

import pandas as pd

cols = pd.MultiIndex.from_tuples([('X', 'a'), ('X', 'b'), ('Y', 'a'), ('Y', 'b')])
df = pd.DataFrame([[1, 3, 4, 2], [5, 7, 8, 6]], columns=cols)

# Here is the renaming part.
mapper = {("Y", "b"): ("Y", "b1")}
df.columns = pd.MultiIndex.from_tuples([mapper.get(x, x) for x in df.columns])

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 BENY
Solution 2 normanius
Solution 3 mouwsy