var table; var canvas_x; var canvas_y; var numTicks; // number of tick marks per axis var dict; // a dictionary that maps some categorical variable c -> [x,y] var tick_dist; // distance between ticks var num_cat; // number of categorical variables var distance_between_x; var axis_len; var y_partitions; var distance_between_y; var max_x; var max_y; var desired_x; var desired_y; var desired_c; var desired_o; // add this later var scale_x; var scale_y; function preload() { table = loadTable("classics.csv", "csv", "header"); } function setup() { // VARIABLE INFORMATION...................................................................... // Canvas information canvas_x = 1250; canvas_y = 1000; // DESIRED x, y, c desired_x = 'words'; desired_y = 'downloads'; desired_c = 'month name'; // Axis info numTicks = 10; // number of tick marks per axis // DERIVED VALUES............................................................................ createCanvas(canvas_x, canvas_y); // DATA POPULATION........................................................................... dict = {}; num_cat = 0; max_x = 0; max_y = 0; // populate the coordinates array for(var i = 0; i < table.getRowCount(); i++) { var coords = []; var x = int(table.getString(i, desired_x)); var y = int(table.getString(i, desired_y)); var c = table.getString(i, desired_c); coords[0] = x; coords[1] = y; // add c -> [x,y] to the dictionary if (c in dict) { var len = dict[c].length; dict[c][len] = coords; if (x > max_x) { // update max_x max_x = x; } if (y > max_y) { // update max_y max_y = y; } } else { dict[c] = []; dict[c][0] = coords; num_cat++; // increment the count of categorical variables } } // AXIS INFO............................................................................ distance_between_x = 150; if (num_cat <= 3) { y_partitions = 1; } if (3 < num_cat && num_cat < 6) { y_partitions = 2; } else { y_partitions = 3; } var graphs_per_line = ceil(num_cat / y_partitions); var blank_x = distance_between_x * (graphs_per_line + 1); // +1 to account for edges var available_x = (canvas_x - blank_x) * y_partitions; axis_len = Math.round(available_x / num_cat); print(axis_len); distance_between_y = (canvas_y - (y_partitions * axis_len))/(y_partitions + 1); // SCALING.................................................................................................. scale_x = (1/max_x) * axis_len; // find the scaling factor for x-values scale_y = (1/max_y) * axis_len; // find the scaling factor for y-values for (key in dict) { // for each categorical variable var num_points = dict[key].length; // find the number of points associated with this categorical variable for (var j = 0; j < num_points; j++) { dict[key][j][0] = dict[key][j][0] * scale_x; // multiply x by scale_x dict[key][j][1] = dict[key][j][1] * scale_y; // multiply y by scale_y } } } function draw() { // background info background(255, 248, 220); // AXIS CREATION ................................................................................................ // axis info stroke(0); // starting axis values var x_x1 = distance_between_x; var x_x2 = distance_between_x + axis_len; var x_y1 = distance_between_y + axis_len; var x_y2 = distance_between_y + axis_len; var y_x1 = distance_between_x; var y_x2 = distance_between_x; var y_y1 = distance_between_y; var y_y2 = distance_between_y + axis_len; // Tick info tick_dist = axis_len / numTicks; // distance between tick marks on x-axis // Overall Title textSize(50); fill(255, 145, 146); text("Trellis Plot", 20, 50); fill(255, 248, 220); text("Trellis Plot", 22, 52); fill(255, 145, 146); text("Trellis Plot", 24, 54); fill(0); // Sub title textSize(30); fill(49, 54, 57); // rect info text(desired_x + " vs. " + desired_y + " by " + desired_c, 25, 90); for (key in dict) { // for each categorical variable if (x_x2 > canvas_x) { // Increment Y & reset X if x seeps off of the page // Move down y x_y1 += distance_between_y + axis_len; x_y2 += distance_between_y + axis_len; y_y1 += distance_between_y + axis_len; y_y2 += distance_between_y + axis_len; // Reset x to start positions x_x1 = distance_between_x; x_x2 = distance_between_x + axis_len; y_x1 = distance_between_x; y_x2 = distance_between_x; } // title strokeWeight(0); textSize(20); fill(49, 54, 57); // Axis title info text(key, Math.round(y_x1 + (x_x2 - x_x1)/4), y_y1 - 10); // axis graphic info stroke(2); strokeWeight(2); // Plot x-axis line(x_x1, x_y1, x_x2, x_y2); // Plot y-axis line(y_x1, y_y1, y_x2, y_y2); // TICK MARKS fill(0); // tick mark info textSize(10); // tick mark info // Y-axis tick marks temp_y = max_y; for (var i = y_y1; i < y_y2; i += tick_dist) { stroke(0); strokeWeight(1); // tick mark info line(y_x1 - 5, i, y_x1 + 5, i); // tick mark strokeWeight(0); // tick value info text(Math.round(temp_y), y_x1 - 50, i + 5); // print tick value (+5 to center number on tick) temp_y = temp_y - (max_y / numTicks); // update value of temp } // X-axis tick marks var temp_x = max_x; for (var i = x_x2; i > x_x1; i -= tick_dist) { strokeWeight(1); // tick mark info line(i, x_y1 - 5, i, x_y1 + 5); // tick mark strokeWeight(0); // tick value info text(Math.round(temp_x), i - 10, x_y1 + 25); // print tick value (+5 to center number on tick) temp_x = temp_x - (max_x / numTicks); // update value of temp } // Axis titles textSize(15); // Axis title info fill(49, 54, 57); // Axis title info // y-axis var y_title_x = y_x1 - 125; var y_title_y = y_y1 + Math.round(axis_len / 2); text(desired_y, y_title_x, y_title_y); // x-axis var x_title_x = x_x1 + Math.round((axis_len / 3)); var x_title_y = y_y2 + 50; text(desired_x, x_title_x, x_title_y); // Plotting points & Interaction.......................................................... for (var i = 0; i < dict[key].length; i++) { // PLOTTING var ellipse_width = 3; // point info noStroke(); // point info fill(47, 53, 107); // point info ellipse(x_x1 + dict[key][i][0], x_y1 - dict[key][i][1], ellipse_width); // plot point // INTERACTION var round_x = Math.round(dict[key][i][0]); // scaled_x var round_y = Math.round(dict[key][i][1]); // scaled_y var real_x = Math.round(dict[key][i][0]/scale_x); // un-scaled x var real_y = Math.round(dict[key][i][1]/scale_y); // un-scaled y if (dist(round_x+x_x1, x_y1 - round_y, mouseX, mouseY) < 5) { fill(255, 145, 146); // rect info rect(mouseX, mouseY, 250, -150); // rect creation textSize(10); // text info fill(255, 248, 220); // text info var string_x = desired_x + " " + real_x; var string_y = desired_y + " " + real_y; var string_c = desired_c + " " + key; var x_val_loc = -10; // the start x location away from mouseX to print text var y_val_loc = 120; // the start y location away from mouseY to print text var y_val_inc = 20; // the amount to increment y (how far apart the lines of text are) // Title for informative box textStyle(BOLD); textSize(15); text("info", mouseX + 10, mouseY - y_val_loc); y_val_loc -= (y_val_inc + 5); textStyle(NORMAL); // normal text info textSize(10); // normal text info // Printing X, Y, C text(string_c, mouseX - x_val_loc, mouseY - y_val_loc); // print c y_val_loc -= y_val_inc; fill(255, 248, 220); // text info text(string_x, mouseX - x_val_loc, mouseY - y_val_loc); // print exact x y_val_loc -= y_val_inc; text(string_y, mouseX - x_val_loc, mouseY - y_val_loc); // print exact y } } // Increment X x_x1 += distance_between_x + axis_len; x_x2 += distance_between_x + axis_len; y_x1 += distance_between_x + axis_len; y_x2 += distance_between_x + axis_len; } }