Data Visualisation Labs

Experiment #1: Visualising a single series of data

For this first data visualisation, I used a line graph to represent the US GDP growth rate per year for the last 10 years. A line graph is useful for this dataset because it is important to emphasise trends in the data over time. Each data point is not entirely independent. Rather, because of economic forces, the GDP growth rate per year is affected by the years immediately prior.

For example, we can see the effects of the 2008 Great Recession as the line dips to -2.8%. As a result of this dip, the US government invested heavily in programs designed to help the US economy regain strength. We can see the effect of these stimulus programs reflected in the graph by the high slope of the line between 2009 and 2010. The line emphasises this better than any other graph form.

One way to make render this data as a physical object would be to create a machine that outputted or consumed coins in a cycle proportional to the data points for each year. This machine would help the viewers understand more clearly that these data points represent the relative growth of the economy, not the absolute size of it — such a distinction is often not properly understood by individuals examining economic data.

Code:

float[] GDP = {2.7, 1.8, -0.3, -2.8, 2.5, 1.6, 2.2, 1.7, 2.4, 2.6, 1.6};
String[] years = {"2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2015", "2016"};
void setup() {
size(600, 375);
background(255 , 255, 255);
fill(100);
textSize(20);
text("US GDP Per Year (2006 - 2016)", 120, 30);

line(0, 200, 600, 200); // X axis

textSize(15);
for (int i = 0; i < GDP.length; i++) {
fill(0);
text(years[i], i*50+31.5, 190);
}
}
void draw() {  
// Read one array element each time through the for loop
float lastElementX = 0;
float lastElementY = 0;
float thisX = 0;
float thisY = 0;
for (int i = 0; i < GDP.length; i++) {
thisX = i*50+50;
thisY = 200-GDP[i]*50;
fill(#FA0000);
ellipse(thisX, thisY, 10, 10);
if (i != 0) // Not first element
line(thisX, thisY, lastElementX, lastElementY);
fill(0);
text(GDP[i]+"%", thisX-45, thisY+10);
lastElementX = thisX;
lastElementY = thisY;
}
}

Experiment #2: Visualising the comparison of multiple sets of data

This next data visualisation represents the two data sets of life expectancy for men and women born in each year from 1900 to 1990. For the sake of clarity, I have only selected years that are a multiple a 10.

A bar graph is most appropriate for this data set since it helps the viewer to properly compare the differences between the male and female bars for each year. Using a bar graph, the viewer can more clearly examine the growing divide in the life expectancies for men and women in the US from 1900 to 1990. Although average life expectancy is generally growing for both men and women over this period, we can see that the rate of increase is different. A bar graph is the best choice to show this because the colours help for comparison purposes.

One way that this data could be represented as a physical object would be to devise a life-sized machine which runs in a loop showing the life expectancies for men and women for each year represented by the heights of movable pegs on the machine. This machine could also emphasise the growing difference by controlling the brightness of a light — the brighter the light, the more extreme the difference.

Code:

float[] maleLifeExpectancy = {46.3, 48.4, 53.6, 58.1, 60.8, 65.6, 66.6, 67.1, 70.0, 71.8};
float[] femaleLifeExpectancy = {48.3, 51.8, 54.6, 61.6, 65.2, 71.1, 73.1, 74.7, 77.4, 78.8};
String [] years = {"1900", "1910", "1920", "1930", "1940", "1950", "1960", "1970", "1980", "1990"};
void setup() {
size(550, 350);
background(255 , 255, 255);
fill(100);
textSize(20);
text("US Life Expectancy (1900 - 1990)", 120, 30);

line(0, 300, 550, 300); // X axis

textSize(10);
for (int i = 0; i < years.length; i++) {
fill(0);
text(years[i], i*50+40, 315);
text("F: "+femaleLifeExpectancy[i], i*50+30, 475-femaleLifeExpectancy[i]*5);
text("M: "+maleLifeExpectancy[i], i*50+30, 490-femaleLifeExpectancy[i]*5);
}
}
void draw() {  
// Read one array element each time through the for loop
textSize(10);
for (int i = 0; i < years.length; i++) {
fill(#FA0000);
rect(i*50+30, 300, 20, 200-femaleLifeExpectancy[i]*5);
fill(#3303FA);
rect(i*50+50, 300, 20, 200-maleLifeExpectancy[i]*5);
}
}

Experiment #3: Animated visualisation

The above graph is the Bitcoin price in USD for the period between 5:45 PM and 6:45 PM on April 16, 2017.

The third data visualisation tracks in real-time the “spot price” of Bitcoin using the public Coinbase API. The code gets the Coinbase price once every minute. I chose to request every minute instead of every second, for example, since the price does not change drastically second to second. To display this data, I decided on a line graph since it helps the user to interpret trends in the data. For something like Bitcoin prices — which can be volatile in the short term — emphasising trends rather than any single data point is important.

I decided against using circles to emphasise each data point, since I want the viewer to focus on trends in the data. Since this program only visualises the previous hour of Bitcoin prices, the minute-by-minute data points are not of great importance; instead, the trend of the data as a whole is what is important.

To represent this is a physical object, we could disregard the specific prices themselves, since for a Bitcoin trader what is important is only relative prices. We could create a machine that inflates a balloon proportional to the price change from the beginning of the period. The machine would continually either deflate or inflate the balloon as prices change. In this way, the viewer could better understand the condition of the Bitcoin market — if the balloon is very inflated, sell; if the balloon is very deflated, buy.

Code:

import http.requests.*;
import java.util.ArrayDeque;
ArrayDeque<Float> priceHistory = new ArrayDeque();
float maxPrice = 0;
float minPrice = 10000; // Reasonable max
void setup(){
size(650, 375);
/* Load queue with zeroes */
for (int i=0; i<60; i++) {// 60 seconds * 60 = 1 hour history
priceHistory.push(0.0);
}
}
void draw(){
background(0);
fill(255);
textSize(20);
text("Bitcoin Price (USD/BTC)", 190, 30);

stroke(255);
line(20, 350, 20, 50);

textSize(10);
// Top
float max = 400-map(maxPrice, maxPrice, minPrice, 350, 50);
line(10, max, 40, max);
text("Max: $"+maxPrice, 30, max-10);

// 3/4
float temp1 = ((maxPrice-minPrice) * 3/4)+minPrice;
float threeFourths = 400-map(temp1, maxPrice, minPrice, 350, 50);
line(10, threeFourths, 40, threeFourths);
text("$"+temp1, 30, threeFourths-10);

// 1/2
float temp2 = ((maxPrice-minPrice) * 2/4)+minPrice;
float twoFourths = 400-map(temp2, maxPrice, minPrice, 350, 50);
line(10, twoFourths, 40, twoFourths);
text("$"+temp2, 30, twoFourths-10);

// 1/4
float temp3 = ((maxPrice-minPrice) * 1/4)+minPrice;
float oneFourth = 400-map(temp3, maxPrice, minPrice, 350, 50);
line(10, oneFourth, 40, oneFourth);
text("$"+temp3, 30, oneFourth-10);

// Bottom
float min = 400-map(minPrice, maxPrice, minPrice, 350, 50);
line(10, min, 40, min);
text("Min: $"+minPrice, 30, min-10);

float lastElementX = 0;
float lastElementY = 0;
float thisX = 0;
float thisY = 0;

float current = getCurrentPrice();
priceHistory.removeFirst(); // Pop oldest price from tail of queue
priceHistory.addLast(current); // Push current price at head of queue

int i = 0;
fill(#FA0000);
stroke(#FA0000);

for (Float number : priceHistory) {
println("Number = " + number);
thisX = i*10+50;
thisY = 400-map(number, maxPrice, minPrice, 350, 50);

if (number > maxPrice) maxPrice = number;
else if (number < minPrice && number != 0.0) minPrice = number;

if (i != 0) // Not first element
line(thisX, thisY, lastElementX, lastElementY);

lastElementX = thisX;
lastElementY = thisY;
i++;
}

println("Min: ", minPrice);
println("Max: ", maxPrice);

delay(60000); // Only refresh every 60 seconds
}
float getCurrentPrice() {
GetRequest get = new GetRequest("https://api.coinbase.com/v2/prices/BTC-USD/spot");
get.send();
JSONObject json = parseJSONObject(get.getContent());
return Float.parseFloat(json.getJSONObject("data").getString("amount"));
}
Show your support

Clapping shows how much you appreciated Zane’s story.