Data Visualisation
Load CSV and JSON data in Processing and build interactive bar charts, scatter plots, line charts, and an animated bubble chart with HSB colour mapping.
Processing was originally designed for teaching visual thinking through code — and it has first-class support for loading and visualising data. This tutorial covers every data format Processing understands and builds up to a fully interactive animated bubble chart driven by a JSON file.
Loading CSV Data
Place your CSV file in the sketch’s data/ folder (Sketch → Add File or just drag it in). Processing’s Table class parses it automatically:
Table data;
void setup() {
data = loadTable("cities.csv", "header"); // "header" reads first row as column names
println("Rows: " + data.getRowCount());
println("Columns: " + data.getColumnCount());
}
A sample cities.csv might look like:
city,population,area,gdp
Tokyo,13960000,2194,1065
New York,8336817,783,1600
London,8982000,1572,731
Access rows and columns by name or index:
for (TableRow row : data.rows()) {
String city = row.getString("city");
int pop = row.getInt("population");
float gdp = row.getFloat("gdp");
println(city + " – pop: " + pop + ", gdp: " + gdp);
}
Use getRow(i) to access a specific row by index, or findRow(value, column) to search for a row.
Loading JSON
loadJSONObject() parses a single object; loadJSONArray() parses an array at the top level.
JSONArray records;
void setup() {
records = loadJSONArray("countries.json");
for (int i = 0; i < records.size(); i++) {
JSONObject country = records.getJSONObject(i);
String name = country.getString("name");
float gdp = country.getFloat("gdp");
int pop = country.getInt("population");
println(name + " gdp=" + gdp + " pop=" + pop);
}
}
A matching countries.json:
[
{"name": "Norway", "gdp": 482.4, "population": 5379000, "continent": "Europe"},
{"name": "Germany", "gdp": 4072, "population": 83240000, "continent": "Europe"},
{"name": "Brazil", "gdp": 1608, "population": 214300000,"continent": "S.America"}
]
For nested objects, chain the getJSONObject() calls as needed.
Bar Chart from CSV
Table data;
float margin = 60;
float barW;
void setup() {
size(800, 500);
data = loadTable("cities.csv", "header");
barW = (width - margin * 2) / (float) data.getRowCount();
}
void draw() {
background(245);
drawBarChart();
}
void drawBarChart() {
float maxPop = 0;
for (TableRow row : data.rows())
maxPop = max(maxPop, row.getFloat("population"));
textAlign(CENTER);
textSize(11);
for (int i = 0; i < data.getRowCount(); i++) {
TableRow row = data.getRow(i);
float pop = row.getFloat("population");
float bh = map(pop, 0, maxPop, 0, height - margin * 2);
float x = margin + i * barW;
float y = height - margin - bh;
// colour bar by index using HSB
colorMode(HSB, 360, 100, 100);
fill(map(i, 0, data.getRowCount(), 0, 280), 70, 90);
colorMode(RGB, 255);
noStroke();
rect(x + 4, y, barW - 8, bh, 3, 3, 0, 0);
fill(80);
text(row.getString("city"), x + barW / 2, height - margin + 15);
text(nf(pop / 1_000_000.0, 0, 1) + "M", x + barW / 2, y - 5);
}
// axes
stroke(180);
strokeWeight(1);
line(margin, height - margin, width - margin, height - margin);
}
Scatter Plot with Mouseover Labels
void drawScatter() {
float maxGDP = 0, maxPop = 0;
for (int i = 0; i < records.size(); i++) {
JSONObject r = records.getJSONObject(i);
maxGDP = max(maxGDP, r.getFloat("gdp"));
maxPop = max(maxPop, r.getFloat("population"));
}
String hovered = null;
for (int i = 0; i < records.size(); i++) {
JSONObject r = records.getJSONObject(i);
float x = map(r.getFloat("gdp"), 0, maxGDP, margin, width - margin);
float y = map(r.getFloat("population"), 0, maxPop, height - margin, margin);
float d = dist(mouseX, mouseY, x, y);
boolean over = d < 10;
fill(over ? color(255, 80, 80) : color(80, 130, 200), 180);
noStroke();
ellipse(x, y, 14, 14);
if (over) hovered = r.getString("name") +
" GDP: $" + nf(r.getFloat("gdp"), 0, 0) + "B";
}
if (hovered != null) {
fill(20);
textAlign(LEFT);
textSize(12);
text(hovered, mouseX + 12, mouseY - 6);
}
}
Line Chart with Animated Drawing
Animate the line being drawn by limiting how many data points are rendered based on frameCount:
float[] values = {12, 19, 8, 27, 22, 34, 30, 41};
int visiblePoints = 0;
void draw() {
background(250);
if (visiblePoints < values.length) visiblePoints++;
stroke(60, 120, 200);
strokeWeight(2);
noFill();
beginShape();
for (int i = 0; i < visiblePoints; i++) {
float x = map(i, 0, values.length - 1, margin, width - margin);
float y = map(values[i], 0, 50, height - margin, margin);
curveVertex(x, y);
}
endShape();
}
curveVertex draws a Catmull-Rom spline through the points so the chart feels smooth rather than jagged.
Colour Mapping with HSB
Switch colorMode to HSB to map a data value to a hue range:
colorMode(HSB, 360, 100, 100, 100);
float hue = map(value, dataMin, dataMax, 240, 0); // blue → red
fill(hue, 80, 90, 80);
Reset to RGB afterwards if other parts of your sketch depend on it:
colorMode(RGB, 255);
Full Example: Animated Bubble Chart
Create data/countries.json as shown above, then run this sketch:
JSONArray records;
float margin = 70;
float t = 0;
void setup() {
size(900, 600);
records = loadJSONArray("countries.json");
textFont(createFont("SansSerif", 12));
}
void draw() {
background(252, 252, 248);
t += 0.012;
drawAxes();
drawBubbles();
drawTitle();
}
void drawAxes() {
stroke(200);
strokeWeight(1);
line(margin, height - margin, width - margin, height - margin);
line(margin, margin, margin, height - margin);
fill(120);
textAlign(CENTER);
textSize(11);
text("GDP (billion USD)", width / 2, height - 10);
pushMatrix();
translate(16, height / 2);
rotate(-HALF_PI);
text("Population", 0, 0);
popMatrix();
}
void drawBubbles() {
float maxGDP = 5000, maxPop = 250_000_000;
String hovered = null;
float hx = 0, hy = 0;
colorMode(HSB, 360, 100, 100, 100);
for (int i = 0; i < records.size(); i++) {
JSONObject r = records.getJSONObject(i);
String name = r.getString("name");
float gdp = r.getFloat("gdp");
float pop = r.getFloat("population");
// animated wobble
float wobble = sin(t + i * 1.3) * 4;
float x = map(gdp, 0, maxGDP, margin, width - margin) + wobble;
float y = map(pop, 0, maxPop, height - margin, margin) + wobble;
// radius proportional to GDP, hue by index
float r_ = map(gdp, 0, maxGDP, 6, 45);
float hue = map(i, 0, records.size(), 0, 300);
boolean over = dist(mouseX, mouseY, x, y) < r_;
fill(hue, over ? 90 : 70, over ? 100 : 85, 85);
noStroke();
ellipse(x, y, r_ * 2, r_ * 2);
// label inside if bubble is big enough
if (r_ > 22) {
fill(0, 0, 100, 90);
textAlign(CENTER, CENTER);
textSize(10);
text(name, x, y);
}
if (over) { hovered = name + " GDP $" + nf(gdp, 0, 0) + "B Pop " +
nf(pop / 1_000_000.0, 0, 1) + "M";
hx = x; hy = y; }
}
colorMode(RGB, 255);
if (hovered != null) {
fill(30, 200);
rect(mouseX + 12, mouseY - 20, textWidth(hovered) + 16, 22, 4);
fill(255);
textAlign(LEFT);
textSize(11);
text(hovered, mouseX + 20, mouseY - 6);
}
}
void drawTitle() {
fill(50);
textAlign(LEFT);
textSize(16);
text("Country GDP vs Population", margin, margin - 10);
}
Key Takeaways
loadTable("file.csv", "header")gives you aTableobject with named columns accessible viarow.getString(),row.getFloat(), etc.loadJSONArray()andloadJSONObject()parse JSON with no external libraries.- Map data values to pixel coordinates with
map(value, dataMin, dataMax, pixelMin, pixelMax). colorMode(HSB, 360, 100, 100)is the most intuitive way to assign perceptually distinct colours across a dataset.- Animated entry and hover interactions transform static charts into explorable, engaging pieces.