转换为具有水平显示和重命名列的多索引数据框

Posted

技术标签:

【中文标题】转换为具有水平显示和重命名列的多索引数据框【英文标题】:convert to multiindex dataframe w/horizontal display and rename columns 【发布时间】:2016-10-24 20:59:58 【问题描述】:

假设我有以下代码:

df1 = pd.DataFrame(np.random.randn(10,4), columns=['A','B','C','D'])
df1['dataframe'] = 'df1'
df2 = pd.DataFrame(np.random.randn(10,4), columns=['A','B','C','D'])
df2['dataframe'] = 'df2'
df = pd.concat([df1, df2])
df.reset_index().set_index(['dataframe','index'])

这将返回一个具有 2 级索引的数据框,即“数据框”和“索引”。我不确定正确的术语是什么,但从视觉上看,第一个索引跨越行而不是列。

我想在这个数据帧上执行 2 项操作,但我正在努力解决。

1) 我想将每个“子数据框”中的列重命名为不同的名称,取自不同的列表,并根据先前分配的第一个索引相应地应用它们。我尝试了以下方法,但如果我再次显示“df”,它就不起作用:

new_cols = ['df1', 'df2']
for i,x in enumerate(new_cols):
    old_cols = df.loc[x].columns.tolist()
    df.loc[x].rename(columns=col_label: '_'.format(x,col_label) for col_label in old_cols, inplace=True)

所以,要清楚,我想要 df1_A...df1_D 和 df2_A...df2_D 而不是 A,B,C,D

2) 我想重新定位这个数据框,使其跨越列,因此我将滚动查看每个“子数据框”,而不是上下滚动。

我已经咨询了 pandas API,但仍然无法正确解决这个问题。

【问题讨论】:

嘿 laszlopanaflex,我在 pandas 食谱中看到一行创建水平多索引的行,这就是你想要的吗?我将该行添加到我的答案中 【参考方案1】:

好的,从那个开始,你首先要再次调用reset_index,如下所示:

df.reset_index(drop=True)

现在您应该在索引中只有一个级别,以及 ABCDdataframe 列。

现在以dataframe 列为中心:

df_pivot = df.pivot(columns='dataframe')

您现在有一个包含分层索引列的数据框,这将允许您滚动并查看顶层的 ABCDdf1df2 就在下面。

如果您只是想探索数据,实际上最好停在那里。您将能够以自然的方式建立索引,而无需重命名列,并且可以通过水平滚动轻松浏览数据。要索引 Adf1 值,您可以编写:

df_pivot['A']['df1']

这是一种自然的语法。但如果你真的想添加下划线,你可以像这样添加它们:

df_pivot.columns = ['_'.join(col[::-1]).strip() for col in df_pivot.columns.values]

由于数据透视表的列由 MultiIndex 表示,df_pivot.columns.values 返回一个元组数组。每个元组类似于('A','df1'),因此如果您想要df1_A 形式的列名,您确实需要我在那里添加的[::1],以便您以相反的顺序加入元组成员。如果您对列名的其他顺序 (A_df1) 感到满意,则可以删除相反的步骤:

df_pivot.columns = ['_'.join(col).strip() for col in df_pivot.columns.values]

【讨论】:

我无法看到它是如何工作的。我假设您建议我不包含原始 sn-p 中的行:df.reset_index().set_index(['dataframe','index'])。否则,“数据框”列(实际上是一个索引)会完全消失。 没错,您不需要原始 sn-p 中的最后一行。将dataframe 保留为一列,以便您可以调用df.pivot,如下所示。 不幸的是,这仍然不起作用。它返回错误 ValueError: cannot label index with a null key。我在 python 2.7【参考方案2】:

使用由原始代码 sn-p 生成的dataframe,我们可以根据它们所属的dataframe 创建两个单独的dataframes,然后从两者中删除"dataframe" 列。然后,我们将新列名分配给两个数据帧的每个 columns 属性。最后,我们将df2 列名列表传递给df1,由于它不存在,pandas 会创建新列,并将df2 的值分配给这些新列。

编辑:得到一行从pandas cookbook 生成多索引的行

df1 = df[df["dataframe"] == "df1"].copy().drop("dataframe",axis = 1)
df2 = df[df["dataframe"] == "df2"].copy().drop("dataframe", axis = 1)
df1.columns = ["df1_" + df1.columns]
df2.columns = ["df2_" + df2.columns]
df1[df2.columns] = df2
df1.columns = pd.MultiIndex.from_tuples([tuple(c.split('_')) for c in df1.columns]); 
print df1

输出(新):

        df1                                     df2                      \
          A         B         C         D         A         B         C   
0 -0.228363  0.675313 -0.076193 -0.805547  0.920632  0.789152  0.275401   
1  0.145603  0.422236  0.623796  0.233534  2.338283 -1.033269 -0.334333   
2 -0.526696  0.307727  0.478437 -0.068488 -0.475583 -0.802997 -0.059091   
3 -1.676880 -0.272451 -0.777794  0.490290  1.456024  0.340962 -0.436860   
4  1.203065 -0.198686 -1.065447  1.188931 -1.140757  0.046975 -2.596953   
5 -0.603939  0.734130 -0.321634  0.150161  2.228873  0.748693 -0.300975   
6  1.028938  0.114437  0.268499  0.260428 -1.896507  0.136147  0.004577   
7 -1.329070 -0.901562 -1.401573  0.715426 -1.711233  0.420301  0.643113   
8  2.033646 -0.550192  1.532104 -1.196995 -0.004135 -1.334320  0.110115   
9 -0.818145 -1.240037  0.880706 -0.625155 -0.672653  0.365357 -0.864840   


          D  
0 -0.888626  
1 -0.952065  
2  0.249387  
3  0.952315  
4 -1.804463  
5 -0.428231  
6 -0.257906  
7  1.551899  
8  0.054855  
9  0.679394  

【讨论】:

这没有任何多索引属性吗? 好吧,他对列说instead of A,B,C,D i'd like df1_A...df1_D and df2_A...df2_D。因此,转换后似乎不应该有一个多索引,尽管我也不太确定。编辑:哦,我没有意识到你是OP。好吧,没关系,我以为你不想要多索引。 是的,想法是仍然具有多索引结构,但“转置”并重命名了基础列。任何帮助表示赞赏!

以上是关于转换为具有水平显示和重命名列的多索引数据框的主要内容,如果未能解决你的问题,请参考以下文章

删除多索引和自动重命名列

如何按列索引重命名列?

如何将熊猫数据框转换为多索引数据框

熊猫将第一个多索引转换为行索引,将第二个多索引转换为列索引

如何将多索引列转换为熊猫数据框的单索引列?

重命名具有任意顺序和重复列名的多索引列