2015-01-21 187 views
8

我可以传递一个StringIO对象以pd.to_csv()就好了:使用Pandas Excelwriter写入到StringIO对象?

io = StringIO.StringIO() 
pd.DataFrame().to_csv(io) 

但使用Excel时,作家,我有很多的麻烦。

io = StringIO.StringIO() 
writer = pd.ExcelWriter(io) 
pd.DataFrame().to_excel(writer,"sheet name") 
writer.save() 

返回一个

AttributeError: StringIO instance has no attribute 'rfind' 

我试图创建一个ExcelWriter对象,而不调用pd.ExcelWriter()但我有一些麻烦。这是我到目前为止已经试过:

from xlsxwriter.workbook import Workbook 
writer = Workbook(io) 
pd.DataFrame().to_excel(writer,"sheet name") 
writer.save() 

但现在我得到一个AttributeError: 'Workbook' object has no attribute 'write_cells'

我如何在Excel格式的数据帧大熊猫保存到一个StringIO对象?

+1

我不确定你可以,至少不容易。 'to_excel'的参数是Excel文件的*路径,而不是实际的文件对象。为什么你要创建一个Excel文件的内存表示呢? – BrenBarn 2015-01-21 02:52:39

+0

使用Flask制作可下载的报告。 – 2015-01-21 16:44:40

回答

16

尽管每个写入引擎支持StringIO,但熊猫期望ExcelWriter构造函数的文件名路径。也许这应该作为Pandas中的bug /功能请求提出。

在这里同时是利用熊猫xlsxwriter引擎解决方法例如:

import pandas as pd 
import StringIO 

io = StringIO.StringIO() 

# Use a temp filename to keep pandas happy. 
writer = pd.ExcelWriter('temp.xlsx', engine='xlsxwriter') 

# Set the filename/file handle in the xlsxwriter.workbook object. 
writer.book.filename = io 

# Write the data frame to the StringIO object. 
pd.DataFrame().to_excel(writer, sheet_name='Sheet1') 
writer.save() 
xlsx_data = io.getvalue() 

更新:作为熊猫0.17的,现在可以到这个更直接做:

# Note, Python 2 example. For Python 3 use: output = io.BytesIO(). 
output = StringIO.StringIO() 

# Use the StringIO object as the filehandle. 
writer = pd.ExcelWriter(output, engine='xlsxwriter') 

请参阅XlsxWriter文档中的Saving the Dataframe output to a string

+0

谢谢 - 单线解决方案完美工作! – 2015-01-22 01:13:38

+3

这只是在熊猫中添加,请参阅:https://github.com/pydata/pandas/pull/10376。将在0.17.0版本发布(概念7月底) – Jeff 2015-06-25 19:34:25

5

看着pandas.io.excel源代码看起来应该不是太多的问题,如果你不介意使用xlwt作为你的作家。其他引擎可能并不是那么困难,但xlwt跳出很容易,因为它的save方法需要一个流或一个文件路径。

为了让熊猫快乐起来,你需要首先传入文件名,因为它会根据引擎检查文件扩展名,以确保它是支持的格式。但是在xlwt引擎的情况下,它只是将文件名填充到对象的路径属性中,然后在save方法中使用它。如果将路径属性更改为流,则在调用save方法时,它将很高兴地保存到该流中。

下面是一个例子:

import pandas as pd 
import StringIO 
import base64 

df = pd.DataFrame.from_csv('http://moz.com/top500/domains/csv') 
xlwt_writer = pd.io.excel.get_writer('xlwt') 
my_writer = xlwt_writer('whatever.xls') #make pandas happy 
xl_out = StringIO.StringIO() 
my_writer.path = xl_out 
df.to_excel(my_writer) 
my_writer.save() 
print base64.b64encode(xl_out.getvalue()) 

那是快速,简单和轻度污染的方式来做到这一点。顺便说一句,一个更简洁的方法是将ExcelWriter(或其中一个现有的子类,如_XlwtWriter)子类化 - 但老实说,在更新路径属性时很少涉及,我投票给你展示简单的方法而不是去稍长的路线。

2

对于那些不使用xlsxwriter作为他们engine=to_excel这里是在内存使用openpyxl一个解决方案:

in_memory_file = StringIO.StringIO() 
xlw = pd.ExcelWriter('temp.xlsx', engine='openpyxl') 
# ... do many .to_excel() thingies 
xlw.book.save(in_memory_file) 
# if you want to read it or stream to a client, don't forget this 
in_memory_file.seek(0) 

解释:ExcelWriter包装类暴露引擎通过.book财产个人工作簿。对于openpyxl,您可以照常使用Workbook.save方法!