在Pandas DataFrame中重命名未命名的多索引列

11

我创建了这个数据框:

import pandas as pd
columns = pd.MultiIndex.from_tuples([("x", "", ""), ("values", "a", "a.b"), ("values", "c", "")])
df0 = pd.DataFrame([(0,10,20),(1,100,200)], columns=columns)
df0

我将 df0 导出到 Excel 文件:

df0.to_excel("test.xlsx")

然后重新加载它:

df1 = pd.read_excel("test.xlsx", header=[0,1,2])
df1

同时我有未命名的列名 Unnamed :....

为了使df1看起来像初始的df0,我运行了以下命令:

def rename_unnamed(df, label=""):
    for i, columns in enumerate(df.columns.levels):
        columns = columns.tolist()
        for j, row in enumerate(columns):
            if "Unnamed: " in row:
                columns[j] = ""
        df.columns.set_levels(columns, level=i, inplace=True)
    return df

rename_unnamed(df1)

做得好。但是否有任何Pandas的方法可以从箱形图中实现这一点?

3个回答

6

自从 pandas 0.21.0 版本以后,代码应该像这样:

def rename_unnamed(df):
    """Rename unamed columns name for Pandas DataFrame

    See https://dev59.com/lVgR5IYBdhLWcg3whtmk

    Parameters
    ----------
    df : pd.DataFrame object
        Input dataframe

    Returns
    -------
    pd.DataFrame
        Output dataframe

    """
    for i, columns in enumerate(df.columns.levels):
        columns_new = columns.tolist()
        for j, row in enumerate(columns_new):
            if "Unnamed: " in row:
                columns_new[j] = ""
        if pd.__version__ < "0.21.0":  # https://dev59.com/lVgR5IYBdhLWcg3whtmk#48186976
            df.columns.set_levels(columns_new, level=i, inplace=True)
        else:
            df = df.rename(columns=dict(zip(columns.tolist(), columns_new)),
                           level=i)
    return df

很棒的解决方案。我正在尝试基于您的函数做类似的事情,但是无法做到。您是否愿意看一下:https://stackoverflow.com/questions/61111336/pandas-dataframes-with-multi-level-columnsrename-a-specific-level-of-column-so? - Bowen Liu

4

结合@jezrael和@dinya的回答,在使用pandas 0.21.0及以上版本(即2017年之后)的情况下,解决此问题的一个选项是:

for i, columns_old in enumerate(df.columns.levels):
    columns_new = np.where(columns_old.str.contains('Unnamed'), '-', columns_old)
    df.rename(columns=dict(zip(columns_old, columns_new)), level=i, inplace=True)

2
您可以使用numpy.wherecontains来按条件进行操作。
for i, col in enumerate(df1.columns.levels):
    columns = np.where(col.str.contains('Unnamed'), '', col)
    df1.columns.set_levels(columns, level=i, inplace=True)

print (df1)
   x values     
          a    c
        a.b     
0  0     10   20
1  1    100  200

很遗憾,在pandas中没有针对此功能的函数。str.contains只适用于Series,所以需要使用for循环。 - jezrael
正如@dinya所说,此代码适用于0.21.0以下版本的pandas。请参阅他/她的答案以获取更新。 - Augusto Sisa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接