/* * Interactive display of demographics by zipcode. * Author: Michael Goldwasser * * Census data from https://github.com/bdenglish/CensusData * City names from http://www.unitedstateszipcodes.org/zip-code-database/ */ // graphical parameter float DIAM = 0.8; // circle diameter as fraction of canvas width float yZip, yLabel; // data set (hardcoded based on our knowledge of format) String CENSUS_FILE = "2010Census.csv"; Table data; int RACE_START = 7; // index of first race related column String label[] = {"White", "Black", "American Indian", "Asian", "Pacific", "Other", "Multiracial", "Latino"}; float pct[] = new float[label.length]; // hand-picked color choices color c[] = {color(0, 0, 255), color(0, 255, 0), color(255, 0, 0), color(255, 255, 0), color(255, 0, 255), color(0, 255, 255), color(50, 150, 250), color(250, 150, 50)}; // current zip code (with inital default) int zip = 63103; String tempZip = ""; String CITY_FILE = "zip_names.csv"; String[] cityname = new String[100000]; void setup() { size(600, 600); textSize(0.25*width*(1-DIAM)); textAlign(CENTER, CENTER); noStroke(); data = loadTable(CENSUS_FILE, "header"); readPercentages(zip); loadNames(); yZip = height*(1-DIAM)/4; yLabel = height - yZip; } void loadNames() { Table temp = loadTable(CITY_FILE, "header"); for (TableRow row : temp.rows()) { int j = row.getInt("zip"); String s = row.getString("acceptable_cities"); if (s.length() == 0) { s = row.getString("primary_city"); } s += ", " + row.getString("state"); cityname[j] = s; } } // Find the row matching given zip and populate new percentages // (sets all to zero otherwise) void readPercentages(int zip) { // set percentages to 0 by default for (int j=0; j < pct.length; j++) { pct[j] = 0.0; } for (TableRow row : data.rows()) { if (row.getInt("Zip") == zip) { // found the match for (int j=0; j < pct.length; j++) { pct[j] = row.getFloat(j + RACE_START); } } } } void draw() { float dist = dist(mouseX, mouseY, width/2, height/2); float mouseAngle = atan2(mouseY-height/2, mouseX-width/2); // note atan2(y,x)! background(255); float theta = -PI; // start at left going clockwise for (int j=0; j < pct.length; j++) { fill(c[j]); float newTheta = theta + TWO_PI * pct[j]; arc(width/2, height/2, width*DIAM, width*DIAM, theta, newTheta); if (dist <= 0.5*width*DIAM && mouseAngle >= theta && mouseAngle < newTheta) { fill(0); textAlign(CENTER, CENTER); text(label[j] + " (" + nf(100*pct[j],1,2) + "%)", width/2, yLabel); } theta = newTheta; } float x = 10; // padding fill(0); textAlign(LEFT, CENTER); text("Zip: ", x, yZip); x += textWidth("Zip: "); if (tempZip.length() > 0) { fill(255, 0, 0); text(tempZip, x, yZip); } else { text(nf(zip, 5) + " (" + cityname[zip] + ")", x, yZip); } } void keyPressed() { if (key >= '0' && key <= '9') { tempZip += key; if (tempZip.length() == 5) { zip = int(tempZip); tempZip = ""; readPercentages(zip); } } }