将Pandas DataFrame转换为类似字节的对象

22

嗨,我正在尝试将我的df转换为二进制并存储在一个变量中。

我的df:

 df = pd.DataFrame({'A':[1,2,3],'B':[4,5,6]})

我的代码:

 import io
 towrite = io.BytesIO()
 df.to_excel(towrite)  # write to BytesIO buffer
 towrite.seek(0)  # reset pointer
 

我得到了AttributeError: '_io.BytesIO' object has no attribute 'write_cells'

完整的回溯信息:

AttributeError                            Traceback (most recent call last)
<ipython-input-25-be6ee9d9ede6> in <module>()
      1 towrite = io.BytesIO()
----> 2 df.to_excel(towrite)  # write to BytesIO buffer
      3 towrite.seek(0)  # reset pointer
      4 encoded = base64.b64encode(towrite.read())  #

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\frame.py in to_excel(self, excel_writer, sheet_name, na_rep, float_format, columns, header, index, index_label, startrow, startcol, engine, merge_cells, encoding, inf_rep, verbose, freeze_panes)
   1422         formatter.write(excel_writer, sheet_name=sheet_name, startrow=startrow,
   1423                         startcol=startcol, freeze_panes=freeze_panes,
-> 1424                         engine=engine)
   1425 
   1426     def to_stata(self, fname, convert_dates=None, write_index=True,

C:\ProgramData\Anaconda3\lib\site-packages\pandas\io\formats\excel.py in write(self, writer, sheet_name, startrow, startcol, freeze_panes, engine)
    624 
    625         formatted_cells = self.get_formatted_cells()
--> 626         writer.write_cells(formatted_cells, sheet_name,
    627                            startrow=startrow, startcol=startcol,
    628                            freeze_panes=freeze_panes)

AttributeError: '_io.BytesIO' object has no attribute 'write_cells'

我刚刚测试了你的代码,在Windows下的pandas 0.23.4中运行良好。 - jezrael
Jezrael,当我打印(towrite)时,它只会打印b'',为什么不是b'/x0/....'?我需要返回二进制数据,我该如何获取它? - Pyd
@pyd - 我通过 df = pd.read_excel(towrite) 进行测试,它返回了 DataFrame。可能是一些 Python 的问题?我在 Python 3.6 下进行了测试。 - jezrael
2
我通过towrite.getvalue()解决了它,感谢你的帮助@jezrael。 - Pyd
3个回答

24

我通过升级pandas到新版本解决了这个问题。

 import io
 towrite = io.BytesIO()
 df.to_excel(towrite)  # write to BytesIO buffer
 towrite.seek(0) 
 print(towrite)
 b''
 print(type(towrite))
 _io.BytesIO
如果你想要查看字节对象,请使用getvalue
print(towrite.getvalue())
b'PK\x03\x04\x14\x00\x00\x00\x08\x00\x00\x00!\x00<\xb

1
使用Excel格式时要非常小心,因为它限制了最大行数和列数。其他各种格式没有这样的限制。 - Asclepius
使用Parquet代替。 - Kermit

11

泡菜

泡菜(Pickle)是Pandas dataframe的一种可复现格式,但仅供受信任的用户在内部使用。由于安全原因,它不适用于与不受信任的用户共享。

import pickle

# Export:
my_bytes = pickle.dumps(df, protocol=4)

# Import:
df_restored = pickle.loads(my_bytes)

这是在 Pandas 1.1.2 版本进行的测试。不幸的是,当处理一个非常大的数据框时,它失败了。但接下来尝试了将每列数据单独进行 Pickling 和并行压缩,最后将其放入列表中进行 Pickling 的方式才成功。或者,您可以将大型数据框分块后再进行 Pickling。

CSV

如果您必须使用 CSV 格式:

df.to_csv(index=False).encode()

请注意,使用CSV时可能会丢失各种数据类型。

Parquet

参见此答案。请注意,使用Parquet时会转换各种数据类型。

Excel

大多数情况下应避免使用它,因为它限制了行和列的最大数量


1
谢谢。我一直允许用户保存一个dtypes字典,但是在阅读了这篇文章之后,我将切换到使用parquet进行持久化 https://towardsdatascience.com/stop-persisting-pandas-data-frames-in-csvs-f369a6440af5 - Kermit
嗨@Asclepius,导出到csv时会丢失哪些数据?我尝试过谷歌搜索,但没有找到太多信息。 - piedpiper
@piedpiper 的例子可以是:浮点数 vs 整数,日期时间格式。 - Asclepius

6

我需要通过boto3将文件对象上传到S3,但它不接受pandas字节对象。因此,在Asclepius的答案基础上,我将对象转换为BytesIO,例如:

from io import BytesIO  
data = BytesIO(df.to_csv(index=False).encode('utf-8'))

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