35

I run an iPython Notebook server, and would like users to be able to download a pandas dataframe as a csv file so that they can use it in their own environment. There's no personal data, so if the solution involves writing the file at the server (which I can do) and then downloading that file, I'd be happy with that.

3
  • I don't think ipython has any feature to solve what you are asking, but you could always code a routine in python that performs the download, and include it in the notebook for your users. Just an idea. Hope it helps. Commented Aug 10, 2015 at 13:20
  • Thanks lrnzcig: that's what it looks like to me. I may try your suggestion. Commented Aug 10, 2015 at 21:09
  • Hi, is it possible to write the dataframe to a csv with pd.to_csv() and then open the csv directly from the ipython server, and then file>Download? Commented Aug 12, 2015 at 20:16

7 Answers 7

44

How about using the FileLinks class from IPython? I use this to provide access to data directly from Jupyter notebooks. Assuming your data is in 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/') 

Run this as a notebook cell and the result will be a list of links to files downloadable directly from the notebook. '/path/to' needs to be accessible for the notebook user of course.

Sign up to request clarification or add additional context in comments.

3 Comments

from IPython.display import FileLink, FileLinks
This does not work in nbviewer (as it tries to handle it but doesn't know how). For nbviewer you can use the following snipet. It just adds ?download at the end of the URL... gitlab.tetras-libre.fr/tetras-libre/jupyter/nbviewer/snippets/4
@daxid this just leads to a sign in page
38

For not too large tables you can use the following code:

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) 

3 Comments

nice! How about for large files? :)
This method has been working like a charm for me in Databricks until this week. Now after I run it in Databricks, the download button will just not show up.
11

If you want to avoid storing CSVs on the server, you can use this Javascript alternative that create the CSV on the client-side:

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) 

Basically, it creates a CSV string in python from the pd dataframe and use it in a small js script that creates a CSV file on the client side and open a saving dialog to save it on the user computer. I tested in my iPython env and it works like a charm!


Note that I am escaping the \n. If I don't do so, the js script string will have the CSV variable written on multiple lines.

For example, print "var csv = '%s'" % industries_revenues.to_csv(index=False).replace('\n','\\n') results to this:

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

Instead of print "var csv = '%s'" % industries_revenues.to_csv(index=False) without the \n escaping that results on a multiple lined and therefore errored javascript:

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

I also escape the ' not to break the variable string in javascript.

2 Comments

I'm getting Javascript error adding output! SyntaxError: missing ; before statement See your browser Javascript console for more details.
I'd also add .replace('\r',''). In windows pandas generates \r\n for line ending which may cause confusion in javascript.
5

A function that creates a csv download link, based on Coen Jonker's answer and similar to Yasin Zähringer's answer except that it uses IPython.display.FileLink so that there is no need to create html code.

The function has an optional delete prompt so you can delete the file after download to keep the notebook server clean.

# 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') 

This is mostly for people who use jupyter notebooks on their own machine. On a shared machine, the use of os.remove might be problematic depending on how you set up file write permissions.

Comments

1

You can use the fact that the notebook can display html for objects, and data urls, to make the content of a csv downloadable:

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() 

Comments

0

The simple method that I found was:

df.to_csv('~/Desktop/file_name.csv') 

Comments

-1

My simple approach to download all the files from the jupyter notebook would be by simply using this wonderful command

!tar cvfz my_compressed_file_name.tar.gz *

This will download all the files of the server including the notebooks.

In case if your server has multiple folders, you might be willing to use the following command. write ../ before the * for every step up the directory.

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

Hope it helps..

1 Comment

I would say once you complete the above steps, you can go to the files section and download all the files in a single tar instead of individually downloading files

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.