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:
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.