动机:
我有一个包含一些数据的CSV,然后将其加载到pandas DataFrame raw_data
中。在单元测试时,我想在raw_data
上进行一些聚合或其他过程,以创建一个新的DataFrame df
,然后确认结果(即df
)是我所期望的。
这意味着我需要在单元测试中指定结果应该是什么样的,包括索引。由于我必须经常这样做,所以手动创建样本进行测试是很乏味的。我想做的是,在交互式会话中,构造正确的结果框架,然后将其转换为可以粘贴到测试模块中的内容。
换句话说,我想要一些函数f
和反函数F
,这样f(df)
是我可以复制和粘贴的,而F(f(df)) == df
示例
df = pd.DataFrame({
'foo': [1, 2, 3],
'bar': ['a', 'b', 'c'],
'baz': ['d', 'e', 'f'],
'qux': ['z', 'y', 'x']
}).set_index(['baz', 'qux'])
我想做的是获取df
,获取一些我可以复制并粘贴到我的测试模块中的东西,并创建df
的精确副本。
我已经尝试了to_dict
和to_json
,但是对于orient
的所有值,要么有一个异常,要么索引没有正确地重新创建(通常,索引的 * 名称 * 被遗漏了)。
下面的代码可以证实这一点:
to_dict
orientations = ['dict', 'split', 'series', 'records', 'list', 'index']
print('\t'.join(['orient', 'eqval', 'valexc', 'eqidx', 'idxexc']))
for orient in orientations:
try:
# Convert df to a dict, which I can __repr__ and then copy and paste
serialized_df = df.to_dict(orient=orient)
# Then, in theory I should be able to recreate the original df from
# the dictionary object
ser_de_df = pd.DataFrame.from_dict(serialized_df, orient=orient)
equal_values = df.equals(ser_de_df)
values_exception = False
except:
equal_values = False
values_exception = True
try:
equal_index = df.index.equals(ser_de_df.index) and df.index.names == ser_de_df.index.names
index_exception = False
except:
equal_index = False
index_exception = True
print('\t'.join(map(str, [orient, equal_values, values_exception, equal_index, index_exception])))
这产生:
orient eqval valexc eqidx idxexc
dict False True False False
split False True False False
series False True False False
records False True False False
list False True False False
index True False False False
因此,orient='index'
创建了一个相等值的DataFrame,但索引丢失了名称。
JSON
下面的代码用于确认orient
的值不适用于JSON:
orientations = {'split', 'records', 'index', 'columns', 'values', 'table'}
print('\t'.join(['orient', 'eqval', 'valexc', 'eqidx', 'idxexc']))
for orient in orientations:
try:
# Convert to JSON, which I could just copy and paste as a string
serialized_df = df.to_json(orient=orient)
# Load back into a DataFrame
ser_de_df = pd.read_json(serialized_df, orient=orient)
equal_values = df.equals(ser_de_df)
values_exception = False
except:
equal_values = False
values_exception = True
try:
equal_index = df.index.equals(ser_de_df.index) and df.index.names == ser_de_df.index.names
index_exception = False
except:
equal_index = False
index_exception = True
print('\t'.join(map(str, [orient, equal_values, values_exception, equal_index, index_exception])))
生产:
orient eqval valexc eqidx idxexc
columns False False False False
table True False True False
index False False False False
split False True False False
records False False False False
values False False False False
所以table
创建相等的值,但不是相等的索引。
当然,我可以手动添加代码来再次正确设置索引名称,但似乎很奇怪,没有一种方法可以一致地序列化DataFrame,包括完整的索引(除了to_pickle
等文件)。
有更好的办法吗?
注:编辑以修复代码中的一个错字,这使我无法找到答案(我在下面添加了答案)。把这个问题放在这里,以防其他人也有同样的问题
3条答案
按热度按时间xyhw6mcr1#
老实说,我浏览了你写的东西,因为我希望(手指交叉)简单的答案是
df.to_clipboard()
。这将复制该框架。你可以把它和df = pd.read_clipboard()
配对。z9gpfhce2#
我的原始代码中有一个错别字,这掩盖了
to_json(orient='table')
可以工作的事实:这将同时保留索引标签和名称。
对于一个简洁的Python对象,你可以这样做:
如果你打印或repr
obj
,你会得到:然后可以复制和粘贴它,然后使用以下命令将其制作回一个嵌套框架:
toe950273#
与
to_dict()
提供的便利性相比,丢失索引名称似乎是一个小缺点,并且知道如果索引名称很重要,那么您所需要的就是第二个副本pasta: