Skip to content

Download data button #2171

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
dfernan opened this issue Nov 19, 2017 · 24 comments
Open

Download data button #2171

dfernan opened this issue Nov 19, 2017 · 24 comments
Labels
feature something new P3 backlog

Comments

@dfernan
Copy link

dfernan commented Nov 19, 2017

Hi,

Would it be possible to add a download data button? Right now the default's option is a png image of the plot but I think it'd be very nice if one could also download the data inside the graph. Thus having a download data in graph button would be really cool.

It'd be a new button in here:
https://github.com/plotly/plotly.js/blob/2ba7bdf30d605794de42d560cab41ebbc8681d29/src/components/modebar/buttons.js

I am not familiar with JS so it's hard for me to make a pull request on this but I do think it'd be a great option.

@etpinard
Copy link
Contributor

@jackparmer @chriddyp @alexcjohnson what do you think, is this within the scope of plotly.js?

@alexcjohnson
Copy link
Collaborator

I'm tempted to say we could add this if/when we create separate data and trace definitions, but the way plotly.js works at present this would be tricky and a bit ambiguous.

Also note that plotly cloud does this already - I realize that this is a few extra steps and not possible in all cases, but I bring it up because a) it may be useful in some cases, and b) knowing what went into its system for splitting the data out makes me more hesitant to build this into plotly.js.

@amellnik
Copy link

As a first step, we could add an optional button that dumps the JSON representation of the plot to a file. This would be easy to implement since there's already a "save and edit this plot in the cloud" button (which many of us can't use).

@jackparmer
Copy link
Contributor

jackparmer commented Nov 20, 2017

+1 @amellnik

What do you think of having the JSON show as indented plaintext within the plot view, that you could copy/paste, instead of downloading to file (or maybe buttons at the top of this plaintext view to download JSON or CSV)? I'd love to be able to quickly inspect the JSON in a JS or embedded graph without being required to download a file.

@jackparmer
Copy link
Contributor

I'm tempted to say we could add this if/when we create separate data and trace definitions, but the way plotly.js works at present this would be tricky and a bit ambiguous.

I think even with missing data or obscure src tags this would still be useful for quickly inspecting how the plot was constructed.

@etpinard
Copy link
Contributor

Is this really necessary?

Typing something like

var gd = document.getElementById('graph')
gd.data // => [{ /* ... */ }]
gd.layout // => { /* */ }

in the console should be easy enough.

@jackparmer
Copy link
Contributor

I'm thinking more about non-JS users here.

@amellnik
Copy link

amellnik commented Nov 20, 2017

@jackparmer I would agree with that or even just to copy the serialized JSON to the clipboard. I also think this should be end-user friendly (and not require using any js).

@etpinard
Copy link
Contributor

Oh sorry, my #2171 (comment) should have said: Is this really necessary in plotly.js proper?

@dfernan
Copy link
Author

dfernan commented Dec 28, 2017

Hi, any updates on this issue? It'd really make my life easier since right now I add a download button at the end of all my dashboards but still not the most ideal/user_friendly...

@etpinard
Copy link
Contributor

@dfernan no updates.

We're still debating (albeit not very intensively during the holidays 😉 ) whether this request has its place in the library.

@dfernan
Copy link
Author

dfernan commented Dec 29, 2017

yes of course, makes sense, please enjoy the holidays :-)

@Cerebrock
Copy link

Please do u.u

@janpickard
Copy link

Hi guys, is there any update on if this is planned to be done or not? would be a big help. thank you!

@RichardNeill
Copy link

In the meanwhile, here is a function I use that provides this feature. I hope it's helpful:

modeBarButtonsToAdd: [{ name: 'downloadCsv', title: 'Download data as csv', icon: Plotly.Icons.disk, click: function(){
var csvData = [];
var header = ['X'] //main header.
for (var j = 0; j < numSeries; j++){
header.push(y_names[j]);
}
csvData.push(header);
var header = [x_title] //subheader
for (var j = 0; j < numSeries; j++){
header.push(y_titles[j]);
}
csvData.push(header);
for (var i = 0; i < data.length; i++){ //data
var line = [data[i][x_name]];
for (var j = 0; j < numSeries; j++){
line.push(data[i][y_names[j]]);
}
csvData.push(line);
}
var csvFile = csvData.map(e=>e.map(a=>'"'+((a||"").toString().replace(/"/gi,'""'))+'"').join(",")).join("\r\n"); //quote all fields, escape quotes by doubling them.
var blob = new Blob([csvFile], { type: 'text/csv;charset=utf-8;' });
var link = document.createElement("a");
var url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", chart_title.replace(/[^a-z0-9_.-]/gi,'_') + ".csv");
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} }],

@yemling
Copy link

yemling commented May 3, 2019

@RichardNeill I'd love to use your code. I've copied it in, but am getting an undefined on numSeries. Is that what you call your rows?

@RichardNeill
Copy link

yes, that's right. I've just quoted the code as I used it. Essentially, csvData[] needs to be a 2D array of arrays, generated from your data as you use it, with a header row if you want one.
In my example, I have one X axis and numSeries different y-axes, each named y_names[j].

The way to do this is:

  1. initialise csvData to empty array.
  2. create the header, as an array containing the column names.
  3. push the header array onto csvData[]
  4. foreach line in your data:
  5. create the line, as an array of data values.
  6. and push the line into csvData[]

there is also an error in the above:
a||""
will coalesce all falsey types (including zero) to the empty string. We actually only want to convert NULL to the empty string, leaving zero as zero.
This is somewhat down to your preference: whether false,null,true should be converted to "false","null","true", or to 0,"",1 .

HTH

@woodwards
Copy link

For those that are interested, I've successfully added a data download button in R plotly/ggplotly.

https://stackoverflow.com/questions/58924824/download-data-from-plotly-graph-via-custom-modebar-button-coded-in-r/58986421#58986421

@ZooBear
Copy link

ZooBear commented Aug 1, 2020

Is there a way to adapt this to Python?

@jackparmer
Copy link
Contributor

This issue has been tagged with NEEDS SPON$OR

A community PR for this feature would certainly be welcome, but our experience is deeper features like this are difficult to complete without the Plotly maintainers leading the effort.

Sponsorship range: $5k-$10k

What Sponsorship includes:

  • Completion of this feature to the Sponsor's satisfaction, in a manner coherent with the rest of the Plotly.js library and API
  • Tests for this feature
  • Long-term support (continued support of this feature in the latest version of Plotly.js)
  • Documentation at plotly.com/javascript
  • Possibility of integrating this feature with Plotly Graphing Libraries (Python, R, F#, Julia, MATLAB, etc)
  • Possibility of integrating this feature with Dash
  • Feature announcement on community.plotly.com with shout out to Sponsor (or can remain anonymous)
  • Gratification of advancing the world's most downloaded, interactive scientific graphing libraries (>50M downloads across supported languages)

Please include the link to this issue when contacting us to discuss.

@alessandroblaco
Copy link

Here is a function that provides this feature. It works for 1-x 1-y scatter

modeBarButtonsToAdd: [
  {
    name: "downloadCsv",
    title: "Download data as csv",
    icon: Plotly.Icons.disk,
    click: (gd) => {
      let data = [
        [gd.layout.xaxis.title.text, gd.layout.yaxis.title.text].join(
          ","
        ),
      ];
      gd.data[0].x.forEach((xvalue, i) =>
        data.push([xvalue, gd.data[0].y[i]].join(","))
      );
      let blob = new Blob([data.join("\r\n")], { type: "text/csv" });
      // import { saveAs } from "file-saver";
      saveAs(
        blob,
        "export.csv"
      );
    },
  },
],

@RichardNeill
Copy link

This will work, but there are a few possible gotchas if you are unlucky with quoted data, data that contains a quote itself, or data that is null. Once I've got the CSV data (and header) into a 2D array, I use:

var csvFile = csvData.map(e=>e.map(a=>'"'+((a??"").toString().replace(/"/gi,'""'))+'"').join(",")).join("\r\n");  

You need to decide how you want to represent the four awkward types ("", null, true, false) in your CSV, should they occur.
My choice represents them as ("","","true","false") respectively. But you might prefer to represent null as "NULL", or as an empty field (i.e. two adjacent commas.) I don't think there is a good, unambiguous way that lets you handle CSV data that potentially contains both nulls and empty strings and lets you distinguish them. But at least we can do something other than crash.

If you want null to be "NULL" rather than "", then change
(a??"")
to
(a??"NULL")

HTH :-)

@joshuakoh1
Copy link

@alessandroblaco Is there a way to export a specific trace that is not hidden instead of the first trace?

@evbo
Copy link

evbo commented Jun 4, 2022

@alessandroblaco thank you! That example is definitely a fine addition to the javascript plotly docs.

Are you familiar with pappa? It is a fast csv writer. I'm wondering if it could be used in your example. The only trouble I see is the data is not simply and Array of Arrays, but more complex than that. Have you tried anything like pappa instead?:
https://www.papaparse.com/docs

@gvwilson gvwilson self-assigned this Jun 10, 2024
@gvwilson gvwilson removed their assignment Aug 2, 2024
@gvwilson gvwilson added feature something new P3 backlog and removed ♥ NEEDS SPON$OR labels Aug 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature something new P3 backlog
Projects
None yet
Development

No branches or pull requests