Tag Archives: D3.js

D3 and Ajax: Updating a Bar Chart With New Data

28 Dec

This is the site I will build.

I have been showing several examples of graphing – mostly using Matplolib. In this example, I will show a bar chart in a webpage using D3 and updated via Ajax requesting a text file with the data. I also have a simple python file that randomly generates 20 data points and feeds it to the text file – my host doesn’t allow me to run the python, but you can get the idea.

I took the code from examples by Scott Murray, and some standard Ajax code block off W3. Making a few changes I was able to get it to work. I like to modify existing code to get a feel for what affects what and how things work. This really helps it all sink in.

This draws the first bar chart when the page loads.

var dataset=[12, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25];
var w = 500;
var h = 100;
var barPadding = 1;

var svg = d3.select(“body”)
.append(“svg”)
.attr(“width”, w)
.attr(“height”, h);

svg.selectAll(“rect”)
.data(dataset)
.enter()
.append(“rect”)
.attr(“x”, function(d, i) {
return i * (w / dataset.length);
})
.attr(“y”, function(d) {
return h – (d * 4);
})
.attr(“width”, w / dataset.length – barPadding)
.attr(“height”, function(d) {
return d * 4;
})
.attr(“fill”, “teal”);

This is my onclick function that uses Ajax and updates the chart:

function clicked(url)
{
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject(“Microsoft.XMLHTTP”);
}
xmlhttp.open(“GET”,url,false);
xmlhttp.send(null);
var newd=xmlhttp.responseText;
var da=newd.split(‘,’);
for (var i in da){
da[i] = parseInt(da[i], 10)
}
document.getElementById(‘test’).innerHTML=xmlhttp.responseText;
svg.selectAll(“rect”)
.data(da)
.attr(“x”, function(d, i) {
return i * (w / da.length);
})
.attr(“y”, function(d) {
return h – (d * 4);
})
.attr(“width”, w / da.length – barPadding)
.attr(“height”, function(d) {
return d * 4;
})
.attr(“fill”, “teal”);
}

All I am doing is requesting a text file of data values (12,34,65,67,32,21,10…), then I split it in to numbers and convert to integers. I also print out the values, but that was just a check for me to see what was being returned. The rest is from an example by Scott Murray on clicking a paragraph to change the data – but with the variable hard coded in the JavaScript. I just passed the textfile to the variable and viola!

Connect the function to a button: <button type=”button” onclick=”clicked(‘data.txt’)”>Click
Me</button>.

My goal was to see how I could have a python file write out a data file and then load it in a webpage, but be able to update the data without refreshing everything on the page.  Could have done it all in Python, with Flask and Jinja but I don’t have a production setup for this. This was the most reasonable way to connect what I may be able to run in production.  Here is a python file that feeds random integers from 5 to 25 to a text file – the one that we will load in.

import random
data=open(“data2.txt”,”w+”)
x=0
for x in range(20):
i=random.randint(5,25)
if x==19:
data.write(str(i))
break
else:
data.write(str(i)+”,”)

data.close()

This could connect to MongoDB, SQLite, or generate data on the fly like it’s doing now. The principle is the same – do something and write it out to text.

D3.js and MongoDB

28 Nov

I have not been shy in my love of MongoDB. The honeymoon is not over. Now I want to graph and visualize my data from MongoDB. I just started looking at D3 – I’m coming to the party a bit late – and it is perfect for this task. I have thrown together a super simple, absurd even, example using a DB I had already populated and some left over CherryPy code. Let me say that reusing code is a good idea – when I can find what I’m looking for. It allows me to throw something together quickly. These are not production samples, but just for me to see that I can get it to work. Enough already. Here is a bar chart using D3 and MongoDB.

d3

A Bar Chart, that should be in SVG, from MongoDB data in D3.js

I have not put this on OpenShift yet, but may.  This bar chart is a simple python script using CherryPy and committing my favorite sin – passing HTML as a variable in a return. One reason to put it on OpenShift is so I can template it in Jinja.  Here is the code:

import cherrypy
from pymongo import Connection

class mongocherry(object):

def index(self):
db=Connection().geo
output =[]
output.append(‘<HTML><HEAD><TITLE>D3 and MONGODB</TITLE><script type=”text/javascript” src=”http://d3js.org/d3.v2.min.js”></script><style type=”text/css”>div.bar {display: inline-block;width: 20px;height: 75px;margin-right: 2px;background-color: teal;}</style></HEAD><BODY><h1>D3 and MongoDB</h1>’)
output.append(‘<script type=”text/javascript”>var dataset=[‘)

for x in db.places.find():
output.append(str(x[“loc”][0])+’,’)
output.append(‘0];’+”\n”+’d3.select(“body”).selectAll(“div”).data(dataset).enter().append(“div”).attr(“class”, “bar”).style(“height”, function(d) {var barHeight = d * 5;return barHeight + “px”;});</script></body></html>’)

i=0
html=””
while i<len(output):
html+=str(output[i])
i+=1

return html

index.exposed = True

cherrypy.config.update({‘server.socket_host’: ‘127.0.0.1’,
‘server.socket_port’: 8000,
})

cherrypy.quickstart(mongocherry())

The Python code prints out HTML that looks like this:

<HTML><HEAD><TITLE>D3 and MONGODB</TITLE>
<script type="text/javascript" src="http://d3js.org/d3.v2.min.js"></script>
<style type="text/css">
div.bar {
display: inline-block;
width: 20px;
height: 75px;
margin-right: 2px;
background-color: teal;}
</style>
</HEAD><BODY>
<h1>D3 and MongoDB</h1>
<script type="text/javascript">
var dataset=[35,35.8,38,39,30,31,31,31,33,25,33,0];
d3.select("body")
.selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
.style("height", function(d) {var barHeight = d * 5;return barHeight + "px";});
</script></body></html>

Not much going on here, just a simple D3.js bar chart – not even done in SVG. The MongoDB part is in the variable dataset[..]. While writing the HTML, the python code loops through my mongodb with for x in db.places.find(): and it grabs the latitude of the data I have with x[“loc”][0] prints it out in the JavaScript variable dataset[]. I add a 0 at the end because I get a trailing comma. Sloppy, but oh well.

I return all the HTML and you get the page displayed at the top of this post. The cool part of marrying D3.js and MongoDB is JSON. I have JSON in my DB and D3 takes JSON.