从iPython Notebook下载CSV

35

我运行一个iPython笔记本服务器,希望用户能够将pandas数据框作为CSV文件下载,以便他们可以在自己的环境中使用。没有个人数据,因此如果解决方案涉及在服务器上编写文件(我可以做到这一点),然后下载该文件,那么我会很高兴。


我认为ipython没有任何功能可以解决你所问的问题,但你可以在Python中编写一个例程来执行下载,并将其包含在笔记本中供用户使用。这只是一个想法,希望能有所帮助。 - lrnzcig
谢谢lrnzcig:我也是这么认为的。我可能会尝试你的建议。 - Tom Slee
你好,使用pd.to_csv()将数据框写入CSV文件,然后直接从IPython服务器打开CSV文件,再通过文件>下载进行下载,这种方式可行吗? - johnchase
7个回答

44

用IPython中的FileLinks类如何?我使用它直接从Jupyter笔记本提供对数据的访问。假设您的数据在pandas dataframe p_df中:

from IPython.display import FileLink, FileLinks

p_df.to_csv('/path/to/data.csv', index=False)
p_df.to_excel('/path/to/data.xlsx', index=False)

FileLinks('/path/to/')

将其作为笔记本单元格运行,结果将是一系列链接列表,可直接从笔记本下载文件。'/path/to'当然需要对笔记本用户可访问。

运行此代码作为笔记本单元格,结果将是一个链接列表,可以直接从笔记本中下载文件。当然,'/path/to'路径需要对笔记本用户可访问。


1
从IPython.display导入FileLink,FileLinks - Seth Gottlieb
这在nbviewer中不起作用(因为它试图处理它但不知道如何处理)。对于nbviewer,您可以使用以下代码片段。 它只是在URL末尾添加“?download”...https://gitlab.tetras-libre.fr/tetras-libre/jupyter/nbviewer/snippets/4 - daxid
1
@daxid 这只是导致一个登录页面。 - rkian

35

对于不太大的表格,您可以使用以下代码:

import base64
import pandas as pd
from IPython.display import HTML

def create_download_link( df, title = "Download CSV file", filename = "data.csv"):
    csv = df.to_csv()
    b64 = base64.b64encode(csv.encode())
    payload = b64.decode()
    html = '<a download="{filename}" href="data:text/csv;base64,{payload}" target="_blank">{title}</a>'
    html = html.format(payload=payload,title=title,filename=filename)
    return HTML(html)

df = pd.DataFrame(data = [[1,2],[3,4]], columns=['Col 1', 'Col 2'])
create_download_link(df)

5
好的!对于大文件怎么办? :) - chris
这个方法在 Databricks 中一直非常好用,但是这个星期开始运行后,下载按钮就不会出现了。 - Bowen Liu
1
这对我有用! - Tanmay Garg

10

如果您想避免在服务器上存储CSV文件,则可以使用此JavaScript替代方案,在客户端创建CSV文件:

from IPython.display import Javascript
js_download = """
var csv = '%s';

var filename = 'results.csv';
var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
if (navigator.msSaveBlob) { // IE 10+
    navigator.msSaveBlob(blob, filename);
} else {
    var link = document.createElement("a");
    if (link.download !== undefined) { // feature detection
        // Browsers that support HTML5 download attribute
        var url = URL.createObjectURL(blob);
        link.setAttribute("href", url);
        link.setAttribute("download", filename);
        link.style.visibility = 'hidden';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    }
}
""" % data_in_dataframes.to_csv(index=False).replace('\n','\\n').replace("'","\'")

Javascript(js_download)

基本上,它从pd数据框中创建一个CSV字符串,并在小的js脚本中使用它,在客户端上创建一个CSV文件并打开保存对话框将其保存到用户计算机上。我在我的iPython环境中测试过,它像魅力一样工作!


请注意,我正在转义\n。如果我不这样做,js脚本字符串将按多行编写CSV变量。

例如,print "var csv = '%s'" % industries_revenues.to_csv(index=False).replace('\n','\\n') 的结果如下:

var csv = 'Industry,sum_Amount\nBanking,65892584.0\n(...)Finance,20211917.0\n'

print "var csv = '%s'" % industries_revenues.to_csv(index=False) 改为带有 \n 转义的代码,以避免产生多行错误的JavaScript:

print "var csv = '%s\\n'" % industries_revenues.to_csv(index=False)

var csv = 'Industry,sum_Amount
Banking,65892584.0
(...)
Finance,20211917.0
'

我也使用'进行转义,以防止在JavaScript中破坏变量字符串。


1
我在添加输出时遇到了Javascript错误! SyntaxError:语句前缺少分号 请查看您的浏览器Javascript控制台以获取更多详细信息。 - AlexLordThorsen
我还会添加.replace('\r','')。在Windows中,pandas生成\r\n作为行结尾,这可能会导致JavaScript混淆。 - g.a

4
根据Coen Jonker的回答并类似于Yasin Zähringer的回答创建CSV下载链接的函数,不同之处在于它使用IPython.display.FileLink,因此无需创建HTML代码。该函数具有可选的删除提示,以便您在下载后删除文件以保持笔记本服务器的清洁。
# Import a module to create a data frame
import pandas
# Import a module to display a link to the file
from IPython.display import FileLink
# Import a module to delete the file
import os
# Create a download function
def csv_download_link(df, csv_file_name, delete_prompt=True):
    """Display a download link to load a data frame as csv within a Jupyter notebook

    Parameters
    ----------
    df : pandas data frame
    csv_file_name : str
    delete_prompt : bool
    """
    df.to_csv(csv_file_name, index=False)
    display(FileLink(csv_file_name))
    if delete_prompt:
        a = input('Press enter to delete the file after you have downloaded it.')
        os.remove(csv_file_name)

# Create an example data frame
df = pandas.DataFrame({'x':[1,2,3],'y':['a','b','c']})
# Use the function to diplay a download link
csv_download_link(df, 'file_name.csv')

本文主要针对在个人计算机上使用Jupyter Notebook的用户。 在共享计算机上,使用os.remove可能会存在问题,具体取决于您如何设置文件写入权限。


1
你可以利用笔记本可以显示html对象和数据url的特性,使csv内容可下载:
import urllib

class CSV(object):
    def _repr_html_(self):
        html = []

        html.append("{},{},{}".format(
                "user",
                "age",
                "city"
            )
        )

        html.append("{},{},{}".format(
                "Alice",
                "39",
                "New York"
            )
        )

        html.append("{},{},{}".format(
                "Bob",
                "30",
                "Denver"
            )
        )

        html.append("{},{},{}".format(
                "Carol",
                "27",
                "Tulsa"
            )
        )


        export = '\n'.join(html)
        export = urllib.quote(export.encode("utf-8"))
        csvData = 'data:application/csv;charset=utf-8,' + export
        return "<a download='export.csv' href='{}' target='_blank'>csv file</a>".format(csvData)

CSV()

0
我发现的简单方法是:
df.to_csv('~/Desktop/file_name.csv')

-1

我下载Jupyter笔记本中的所有文件的简单方法是使用以下命令:

!tar cvfz my_compressed_file_name.tar.gz *

这将下载服务器上的所有文件,包括笔记本。

如果您的服务器有多个文件夹,您可能需要使用以下命令。对于每个向上的目录步骤,在*之前写入../。

tar cvfz zipname.tar.gz ../../*

希望能帮到您。


我认为一旦您完成了上述步骤,就可以转到文件部分,并下载所有文件而不是单独下载文件。 - Ash Upadhyay

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