如何在pandas DataFrame中存储行和列索引的名称?

5

我有一个带有DataFrame的数据结构,行和列都有名称:

import numpy as np
import pandas as pd

I = pd.Index(["a", "b", "c", "d"], name="rows")
C = pd.Index(["col0", "col1", "col2"], name="cols")
df = pd.DataFrame(data=np.random.rand(4, 3),
                  index=I,
                  columns=C)

我尝试过用多种格式(例如Excel、CSV)存储它,但是在重新读取文件时,名称会丢失(可能我错过了一些选项)。Msgpack 虽然可行,但被标记为实验性的,因此我现在更愿意避免使用它。我也想避免使用 pickle。是否有任何方法(格式和选项)可以存储这两个索引的名称?
编辑: 我知道如何使用pandas编写和读取CSV。问题是如何保存列索引和行索引的名称。

代码的第一个版本是错误的(名称没有被保存)。对此我感到抱歉。 - Mathieu Dubois
访问和导出索引和列的名称根本不是问题。然而,我正在考虑一种适当的方式来导入导出的数据,因为只有在使用多重索引时才有意义。但是,您不需要使用多重索引来正确访问您的数据。 - albert
4个回答

8
你可以使用 HDF。
import numpy as np
import pandas as pd
I = pd.Index(["a", "b", "c", "d"], name="rows")
C = pd.Index(["col0", "col1", "col2"], name="columns")
df = pd.DataFrame(data=np.random.rand(4,3), index=I, columns=C)
print(df)

columns      col0      col1      col2
rows                                 
a        0.098497  0.918954  0.642800
b        0.168266  0.678434  0.455059
c        0.434939  0.244027  0.599400
d        0.877356  0.053085  0.182661

df.to_hdf('test.hdf', 'test')
print(pd.read_hdf('test.hdf'))

columns      col0      col1      col2
rows                                 
a        0.098497  0.918954  0.642800
b        0.168266  0.678434  0.455059
c        0.434939  0.244027  0.599400
d        0.877356  0.053085  0.182661

似乎是完美的交易! - Mathieu Dubois

3
您可以使用.to_csv()将DataFrame导出为csv文件,并使用.read_csv()读取它。我根据您已有的代码进行了如下扩展:
#!/usr/bin/env python3
# coding: utf-8

import numpy as np
import pandas as pd

I = pd.Index(["a", "b", "c", "d"], "rows")
C = pd.Index(["col0", "col1", "col2"], "cols")
df = pd.DataFrame(data=np.random.rand(4,3), index=I, columns=C)

# export DataFrame to csv
df.to_csv('out.csv')

# set index_col in order to read first column as indices
df_in = pd.read_csv('out.csv', index_col=0)

所以DataFrame df 的样子是这样的:
       col0      col1      col2
a  0.590016  0.834033  0.535310
b  0.421589  0.897302  0.029500
c  0.373580  0.109005  0.239181
d  0.473872  0.075918  0.751628

csv文件 out.csv 的格式如下:

,col0,col1,col2
a,0.5900160748408918,0.8340332218911729,0.5353103406507513
b,0.42158899389955884,0.8973015040807538,0.029500416731096046
c,0.37357951184145965,0.10900495955642386,0.2391805787788026
d,0.47387186813644167,0.07591794371425187,0.7516279365972057

读取数据后,得到的DataFrame是df_in,如下所示:
       col0      col1      col2
a  0.590016  0.834033  0.535310
b  0.421589  0.897302  0.029500
c  0.373580  0.109005  0.239181
d  0.473872  0.075918  0.751628

所以df2df完全相同,这表明导出和期望的导入正在按照预期工作。

编辑以导出列和索引名称

df.to_csv('out.csv', index_label=[df.index.name, df.columns.name])

然而,这样做会使得重新导入变得有些困难,因为列名被添加为额外的列。通常,这对于多索引数据是有用的,但在此处会导致额外的空列。
因此,我建议仅导出索引名称:
# export DataFrame to csv
df.to_csv('out.csv', index_label=df.index.name)

# set index_col in order to read first column as indices
df_in = pd.read_csv('out.csv', index_col=0)

这将导致 df_in 变为:

          col0      col1      col2
rows                              
a     0.442467  0.959260  0.626502
b     0.639044  0.989795  0.853002
c     0.576137  0.350260  0.532920
d     0.235698  0.095978  0.194151

我不知道为什么你需要导出索引和列的名称。如果你只是想访问行或列的名称,可以像这样获取它们的标签:

column_labels = df.columns.get_values()
>>> array(['col0', 'col1', 'col2'], dtype=object)

index_labels = df.index.get_values()
>>> array(['a', 'b', 'c', 'd'], dtype=object)

我的代码出现了一个错误(很抱歉):名称没有正确设置。我知道如何保存为CSV文件。问题是要保存索引的名称。在你的代码中,df_in的列索引将不会被设置。 - Mathieu Dubois
我也尝试过使用 index_label,但没有成功(正如你所提到的,它很难重新读取)。我认为 CSV 文件无法正确处理它。我希望 Excel 能够工作,但据我所知它并不能。 - Mathieu Dubois
你需要这些名称做什么? - albert
好的,我不需要这些名称,但有时候拥有它们很方便(特别是对于多索引或复杂数据框)。这是我设置它们的主要原因。 - Mathieu Dubois
我已经阅读了你的回答,但它并不是我要找的(我只想存储名称,而不是访问值)。@Goyo的答案基于HDF格式提供了一个简单的解决方案。 - Mathieu Dubois

1
你的DataFrame是否真的有索引名称?在我的电脑上,我需要写
I = pd.Index(["a", "b", "c", "d"], name="rows")

替代

I = pd.Index(["a", "b", "c", "d"], "rows")

为了实际分配名称。然后使用df.to_csv()和pd.read_csv(),索引名称确实得到保留(在csv中,索引名称只是像另一列一样保存)。

如果这不起作用,您需要能够使用Python以外的程序打开它吗?如果不需要,您可以使用pickle,它应该不会改变对象:

import pickle

pickle.dump(df, open("File.pickled", "wb"))

df_read = pickle.load(open("File.pickled", "rb"))

编辑:如果你想在使用to_csv()时保留列索引的名称,你可以尝试以下hack方法:

保存它 (将列索引转换为行,因此将其列索引名称设置为行索引值)

df.T.reset_index().T.to_csv("DataFrame.csv")

然后使用以下两种方法之一来读取它,第一个方法(略微)更快:

df_read = pd.read_csv("DataFrame.csv", index_col=0)
df_read.columns = df_read.loc['cols']
df_read = df_read.drop('cols', axis=0)

或者

df_read = pd.read_csv("DataFrame.csv", index_col=0)
df_read = df_read.T.set_index('cols').T

糟糕!刚刚意识到...谢谢,我会更正问题。然而问题在于当列和行都有名称时。 - Mathieu Dubois
呃,我也更倾向于避免使用pickle - Mathieu Dubois
@MathieuDubois 使用pickle可以保存列和行的名称,但如果您想避免使用它,可以在保存到CSV之前将列索引设置为行。我已经更新了我的答案,并提供了相应的代码。 - Borja

0

header=True (用于列名) 和 index=True (用于索引值) 在 df.to_csv 中应该可以解决问题。文档中说两个都默认是 True。然而,在加载后,您将需要手动设置索引,因为它被加载为普通列。为此,我已经为索引添加了一个名称:

import numpy as np
import pandas as pd

# your code:
I = pd.Index(["a", "b", "c", "d"], "rows")
C = pd.Index(["col0", "col1", "col2"], "cols")
df = pd.DataFrame(data=np.random.rand(4, 3),
                  index=I,
                  columns=C)

# name the index
I.name = 'index'

print "original:"
print df
print ""

df.to_csv("~/test.csv", index=True, header=True)

df2 = pd.read_csv("~/test.csv").set_index('index')

print "read from disk:"
print df2
print ""

输出:

original:
           col0      col1      col2
index                              
a      0.455378  0.830872  0.495953
b      0.707146  0.832009  0.112540
c      0.894997  0.156364  0.521047
d      0.775462  0.482554  0.578177

read from disk:
           col0      col1      col2
index                              
a      0.455378  0.830872  0.495953
b      0.707146  0.832009  0.112540
c      0.894997  0.156364  0.521047
d      0.775462  0.482554  0.578177

我的代码出现了一个错误(很抱歉):名称没有正确设置。问题在于如何保存行索引的名称和列索引的名称。 - Mathieu Dubois

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