我有一个以csv格式存储在数据库中的pandas数据框(不是用户输入)。我在视图中提取了此csv,然后希望将两列传递到我的模板和plotly.js图表中:日期列和值列。我应该如何正确地将它们作为模板变量传递,以使javascript正确地解释它们?
尝试的解决方案:
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>
该绘图实际上可以正确地绘图,但是很明显,日期没有作为日期对象传递,因为x轴的日期在字符串和方括号内。我需要将df列通过plotly javascript识别为日期/值。
我认为我的中途解决方案有点不合时宜,图表无法正确解释。
以下是数据框的示例:
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
答案 0 :(得分:0)
您在这里的过程有几个步骤:
第1步很棒,但第2步方法有点奇怪。通常,这称为序列化;我强烈建议您不要使用隐藏输入。您的目标是将熊猫数据框转换为JS变量,这比您想象的要简单。
您可以通过将JavaScript更改为以下内容来消除隐藏的输入:
var trace1 = {
x: {{dates|safe}},
y: {{values|safe}},
type: 'scatter',
};
var data = [trace1];
Plotly.newPlot('myDiv', data, {}, {showSendToCloud: true});
因为您可以将Django模板看作只是复制/粘贴:无论您将标记放在HTML还是JS部分中,它将粘贴您的数据。
为了将来参考,Pandas有一个名为df.to_json()
的序列化方法,该方法是为此翻译而构建的,并且具有用于控制日期格式和内容的内置选项。那是最好的工具,但是在技术上并不是必须的。文件:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_json.html
对于第三步,plotly期望使用JS Date对象,并且要给它提供字符串-您需要首先使用Date.parse()解析它们
您可以这样做的一种方法是将Date.parse()函数映射到日期字符串数组上,如下所示:
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})