I am unable to figure out how to create a NVD3 chart (stackedArea) in Python from a Pandas Dataframe using the python-nvd3 wrapper. A demo with a list of integers is working without issues.
My intitial Data consists a series of dates and a series of values (float):
type(df['Value'])
Out[85]: pandas.core.series.Series
type(df['Start'])
Out[86]: pandas.core.series.Series
type(df['Value'][1])
Out[96]: numpy.float64
type(df['Start'][1])
Out[102]: pandas.tslib.Timestamp
I convert both series to lists and the TimeStamp ('Start') to a string.
type(df['Start'].dt.strftime('%Y-%m-%d %H:%M:%S').tolist())
Out[100]: list
type(df['Value'].values.tolist())
Out[101]: list
The reason I convert the TimeStamp object string is because when I directly supply it, I get the following error message in Django:
Timestamp('2016-02-05 00:00:00') is not JSON serializable
However, the chart remains empty. The length of both list is similar.
The initial data:
df['Start'].dt.strftime('%Y-%m-%d %H:%M:%S').tolist()
Out[104]:
['2016-02-05 00:00:00',
'2016-02-05 01:00:00',
'2016-02-05 02:00:00',
'2016-02-05 03:00:00',
'2016-02-05 04:00:00',
'2016-02-05 05:00:00',
'2016-02-05 06:00:00',
'2016-02-05 07:00:00',
'2016-02-05 08:00:00',
'2016-02-05 09:00:00',
'2016-02-05 10:00:00',
'2016-02-05 11:00:00',
'2016-02-05 12:00:00',
'2016-02-05 13:00:00',
'2016-02-05 14:00:00',
'2016-02-05 15:00:00',
'2016-02-05 16:00:00',
'2016-02-05 17:00:00',
'2016-02-05 18:00:00',
'2016-02-05 19:00:00',
'2016-02-05 20:00:00',
'2016-02-05 21:00:00',
'2016-02-05 22:00:00',
'2016-02-05 23:00:00',
'2016-02-05 00:00:00',
'2016-02-05 01:00:00',
'2016-02-05 02:00:00',
'2016-02-05 03:00:00',
'2016-02-05 04:00:00',
'2016-02-05 05:00:00',
'2016-02-05 06:00:00',
'2016-02-05 07:00:00',
'2016-02-05 08:00:00',
'2016-02-05 09:00:00',
'2016-02-05 10:00:00',
'2016-02-05 11:00:00',
'2016-02-05 12:00:00',
'2016-02-05 13:00:00',
'2016-02-05 14:00:00',
'2016-02-05 15:00:00',
'2016-02-05 16:00:00',
'2016-02-05 17:00:00',
'2016-02-05 18:00:00',
'2016-02-05 19:00:00',
'2016-02-05 20:00:00',
'2016-02-05 21:00:00',
'2016-02-05 22:00:00',
'2016-02-05 23:00:00']
df['Value'].values.tolist()
Out[105]:
[7330.75,
7127.5,
6994.75,
7116.75,
7636.0,
8329.5,
9193.0,
10152.5,
11091.5,
11851.75,
12329.75,
12674.0,
12800.75,
12707.75,
12641.75,
12783.5,
13210.0,
13593.5,
13842.75,
13869.5,
13901.0,
13984.0,
13986.5,
13998.5,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
11.25,
355.0,
1256.5,
2398.75,
3148.25,
3171.5,
2814.25,
2200.0,
1319.0,
440.5,
17.25,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0,
0.0]
As requested the relevant code as part of a Django project: views.py
from django.shortcuts import render_to_response, RequestContext
from datetime import date, timedelta
from random import randint
from random import shuffle, randint
from itertools import islice
from django.utils.translation import ugettext_lazy as _
import random
import requests
from requests_ntlm import HttpNtlmAuth
import time
import datetime
from json2html import *
import json
from pandas.io.json import json_normalize
import pandas as pd
import numpy as np
def demo_stackedareachart(request):
"""
stackedareachart page
"""
input_start = datetime.date.today() + datetime.timedelta(days=1)
input_end = datetime.date.today() + datetime.timedelta(days=2)
parameters={'start':'today+1','end':'today+1','timeZone':'UCT','resolution':'Hour','filterTimeBy':'ValueTime', 'dataPointsToReturn':'All','getSamples':'false'}
seriesID = 2194
seriesID2 = 2193
session = requests.Session()
session.auth = HttpNtlmAuth('XXXX\\XXXX','XXXXXXXXXXXX', session)
session.headers={"content-type":"application/json"}
r = session.get('XXXXXXXXXXX' + str(seriesID) + "%2C" + str(seriesID2), params=parameters, stream=False)
js = r.json()
df = json_normalize(js, 'DataPoints',['SeriesId','SamplingTime'])
df['SamplingTime'] = pd.to_datetime(pd.Series(df['SamplingTime']))
df['Start'] = pd.to_datetime(pd.Series(df['Start']))
nb_element = 150
xdata = df['Start'].values.astype('int64')
xdata = map(long, xdata)
ydata = df['Value'].values.tolist()
extra_serie1 = {"tooltip": {"y_start": "", "y_end": " balls"}}
chartdata = {
'x': xdata,
'name1': 'series 1', 'y1': ydata, 'extra1': extra_serie1,
# 'name2': 'series 2', 'y2': ydata2, 'extra2': extra_serie2,
}
charttype = "stackedAreaChart"
chartcontainer = 'stackedareachart_container' # container name
data = {
'charttype': charttype,
'chartdata': chartdata,
'chartcontainer': chartcontainer,
'extra': {
'x_is_date': True,
'x_axis_format': '%d %m %Y %H %M %S',
'tag_script_js': True,
'jquery_on_ready': False,
},
}
return render_to_response('stackedareachart.html', data)
stackedareachart.html
{% extends "__base.html" %}
{% block content %}
{% load static %}
{% load nvd3_tags %}
<head>
{# Jquery CDN : Needed when using jquery_on_ready=True #}
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
{% include_chart_jscss %}
{% load_chart charttype chartdata chartcontainer extra %}
</head>
<body>
{% include_container chartcontainer 400 600 %}
</body>
{% endblock %}
UPDATE 1:
I made progress by converting the Timestamp to int64 and then to long. The only problem left is, that it returns the same values regardless of the day, resulting in this plot.
UPDATE 2: So I assume it all boils down to correctly converting df['Start'] to the correct Integer. But I am stuck at finding the correct syntax. This is what I got so far:
xdata = df['Start'].dt.to_pydatetime()
xdata = map(lambda x: int(time.mktime(q[x].timetuple())*1000), q)
But I fail at the second command.
IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices