简体   繁体   中英

Django/plotly.js: Pass Pandas Dataframe columns to template chart

I have a pandas dataframe (not user input) stored in my database as a csv. I extract this csv in my view, and then want to pass two columns to my template and into a plotly.js chart: a date column and a value column. How should I correctly pass these as template variables in order for plotly javascript to interpret them correctly?

attempted solution:

views.py

def chart_function(request):
       df = #dataframe is extracted from DB using some code
       dates = list(pd.to_datetime(df['dates']))
       values = [float(i) for i in list(df['values'])]
       return render(request, template.html, {'values': values, 'dates': dates})   

template.html:


<div id="myDiv"></div>
<input type = "hidden" id = "dates" name = "variable" value = "{{dates|safe}}">
<input type = "hidden" id = "values" name = "variable" value = "{{values|safe}}">


<script type = "text/javascript">
var dates = document.getElementById("dates").value.split(',');
var values = document.getElementById("values").value.split(',');

var trace1 = {
  x: dates,
  y: values,
  type: 'scatter',
};


var data = [trace1];
Plotly.newPlot('myDiv', data, {}, {showSendToCloud: true});
</script>


The plot actually plots somewhat correctly, but it's clear that the dates are not being passed as date objects because the x axis has dates within strings and brackets. I need the df columns to be recognized as dates/values by plotly javascript.

I think my halfway solution is a little hacked together, and is not being interpreted correctly by the chart.

heres a sample of the dataframe:


Date          Value          
2019-01-03    3.0
2019-01-04    4.0
2019-01-05    5.0
2019-01-06    6.0
2019-01-07    7.0
2019-01-08    8.0
2019-01-09    9.0
2019-01-10   10.0
2019-01-11   11.0
2019-01-12   12.0
2019-01-13   13.0
2019-01-14   14.0
2019-01-15   15.0
2019-01-16   16.0


Your process here has a few steps:

  1. Get the data out of your data storage (usually a database, but a CSV in this case)
  2. Put that data in the template
  3. Parse the data in JS
  4. Plotly

Step 1 is great, but step 2 you have a bit of an odd methodology. Generally this is called serialization; I'd highly advise against using hidden inputs the way you are. Your goal is to translate your pandas dataframe into a JS variable, it's simpler than you think.

You can eliminate your hidden inputs by changing your javascript to just this:

var trace1 = {
  x: {{dates|safe}},
  y: {{values|safe}},
  type: 'scatter',
};


var data = [trace1];
Plotly.newPlot('myDiv', data, {}, {showSendToCloud: true});

Because you can think of the Django template as just copy/paste: It's going to paste your data wherever you put that tag whether that's in the HTML part or the JS part.

For future reference, Pandas has a serialization method called df.to_json() which is built for this translation, and that has built-in options for controlling date formatting and stuff. That's the best tool to use but it's not technically necessary here. Docs: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_json.html

For the third step, plotly is expecting JS Date objects, and you're giving it strings--you need to parse them first using Date.parse()

One way you could do that would be to map the Date.parse() function over the array of date strings like so:

unparsedDates = {{dates|safe}}

parsedDates = unparsedDates.map(dateString => new Date(dateString) )

var trace1 = {
  x: parsedDates,
  y: {{values|safe}},
  type: 'scatter',
};


var data = [trace1];
Plotly.newPlot('myDiv', data, {}, {showSendToCloud: true})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM