├── .gitignore
├── LICENSE
├── README.md
├── examples
├── api_example
│ ├── index.html
│ └── mySketch.js
├── bar_example
│ ├── index.html
│ └── mySketch.js
├── box_plot_example
│ ├── index.html
│ └── mySketch.js
├── density_plot_example
│ ├── index.html
│ └── mySketch.js
├── dom_control_example
│ ├── index.html
│ └── mySketch.js
├── facetingexample
│ ├── index.html
│ └── mySketch.js
├── firstexample
│ ├── index.html
│ └── mySketch.js
├── secondexample
│ ├── index.html
│ └── mySketch.js
├── simplearraytest
│ ├── index.html
│ └── mySketch.js
├── simplesvg_barexample
│ ├── index.html
│ └── mySketch.js
├── simplesvg_boxexample
│ ├── index.html
│ └── mySketch.js
├── simplesvg_example
│ ├── index.html
│ └── mySketch.js
└── testexample
│ ├── datasets.js
│ ├── diamonds.json
│ ├── index.html
│ └── mySketch.js
├── ggplot2-cheatsheet.pdf
├── lib
├── p5.plot.js
├── p5.plot.old.js
├── p5.simpleplot.js
└── p5.simpleplotsvg.js
├── rtests
└── testing
│ ├── .RData
│ ├── .Rhistory
│ ├── testbar.R
│ └── testing.Rproj
└── support
├── datasets.js
├── diamonds.json
├── economics.json
├── mpg.json
└── seals.json
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .git/
3 | .Rproj.user
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Integrated Digital Media, NYU
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # p5.js-plot
2 | p5.plot!
3 |
4 | ## Documentation
5 | ### JSONs
6 | ```
7 | // to use existing datasets
8 | var diamonds, mpg, seals, economics;
9 |
10 | function preload() {
11 | diamonds = loadJSON("https://raw.githubusercontent.com/IDMNYU/p5.js-plot/master/support/diamonds.json");
12 | seals = loadJSON("https://raw.githubusercontent.com/IDMNYU/p5.js-plot/master/support/seals.json");
13 | mpg = loadJSON("https://raw.githubusercontent.com/IDMNYU/p5.js-plot/master/support/mpg.json");
14 | economics = loadJSON("https://raw.githubusercontent.com/IDMNYU/p5.js-plot/master/support/economics.json");
15 | }
16 | ```
17 | ### Getting Started
18 | ```
19 | // initiate a variable
20 | let foo;
21 | function setup(){
22 | // create a new p5.plot instance and store it in the variable
23 | foo = new p5.Plot();
24 | }
25 | ```
26 | The p5.plot object instance takes in the following constructors:
27 | - data
28 |
29 | Takes in an array of objects
30 | - xkey
31 |
32 | Specify the key value for x axis.
33 | - ykey
34 |
35 | Specify the key value for y axis.
36 | - type
37 |
38 | Supports "line", "point", "area", "density", "box", "histogram", "pie"
39 | - left
40 |
41 | The left position of the graph. Takes a number.
42 | - top
43 |
44 | The top position of the graph. Takes a number.
45 | - right
46 |
47 | The right position of the graph. Takes a number.
48 | - bottom
49 |
50 | The bottom position of the graph. Takes a number.
51 | - background
52 |
53 | Whether to draw background. Takes ```true``` or ```false```.
54 | - backgroundcolor
55 | - gridcolor
56 | - gridweight
57 | - cols
58 |
59 | The number of columns of the grid.
60 | - rows
61 |
62 | The number of the rows of the grid.
63 | - fillcolor
64 |
65 | The filling color of the graph.
66 | - strokecolor
67 | - strokeweight
68 | - pointdiameter
69 |
70 | The numeric value of the diameter of the points on the graph.
71 | - bins
72 |
73 | Number of bins to group the datasets.
74 |
75 |
76 |
77 | ### Types of Graphs
78 | - Line graph
79 |
80 | {type: 'line'}
81 |
82 | - Point graph
83 |
84 | {type: 'point'}
85 |
86 | - Area graph
87 |
88 | {type: 'area'}
89 |
90 | - Density graph, one contineous variable
91 |
92 | {type: 'density'}
93 |
94 | - box and whisker plot
95 |
96 | {type: 'box'}
97 |
98 | - Histogram
99 |
100 | {type: 'histogram'}, one contineous variable
101 |
102 | - Pie chart
103 |
104 | {type: 'pie'}
105 |
106 | ### Functions
107 | - redraw()
108 |
109 | Put this in draw to use the hover function.
110 | Example:
111 | ```
112 | foo.redraw()
113 | ```
114 | - hover()
115 |
116 | Now supports point graph, line graph and histogram.
117 | Example:
118 | ```
119 | foo.hover(mouseX, mouseY, 'point');
120 | foo.hover(mouseX, mouseY, 'bin');
121 | ```
122 | ## WORKING ON:
123 | - Fixing graphs by incorporating multiple xkey values and multiple colors
124 | (line graph, point graph, area graph done)
125 |
126 |
127 | ## TO DO:
128 | - Fix hover function (a new way to add data in each graph function)
129 | - multiple xkeys AND multiple ykeys faceting
130 | - graph annotation, such as title
131 | - scales, coordinate system
132 |
--------------------------------------------------------------------------------
/examples/api_example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/api_example/mySketch.js:
--------------------------------------------------------------------------------
1 | let earthquakes;
2 | let myData = [];
3 | let foo;
4 |
5 | function preload(){
6 | earthquakes = loadJSON('https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson');
7 | }
8 |
9 | function setup(){
10 | for (let i=0; i< earthquakes.features.length; i++){
11 | let lat = earthquakes.features[i].geometry.coordinates[0];
12 | let long = earthquakes.features[i].geometry.coordinates[1];
13 | myData.push({lat, long});
14 | }
15 | createCanvas(windowWidth, windowHeight);
16 | background(255);
17 | // CONSTRUCTOR:
18 | foo = new p5.Plot({left: width*0.2, top: height*0.3, right: width*0.8, bottom: height*0.7, fillcolor:[[255, 0, 0]], backgroundcolor:100, rows:0, cols:0 });
19 | foo.plot({data: myData, type: 'point', xkey: 'lat', ykey: 'long'});
20 | }
21 |
22 | function draw() {
23 | background(255);
24 | foo.redraw();
25 | foo.hover(mouseX, mouseY, 'point');
26 | }
27 |
--------------------------------------------------------------------------------
/examples/bar_example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/bar_example/mySketch.js:
--------------------------------------------------------------------------------
1 | var foo; // p5.Plot() object
2 |
3 | var barData = [{"x":"a", "y":10}, {"x":"b", "y":16}, {"x":"c", "y":5}];
4 | var barData2 = [{"x":"a"}, {"x":"b"}, {"x":"c"}, {"x":"a"}, {"x":"a"}, {"x":"b"}];
5 |
6 | function setup() {
7 | createCanvas(windowWidth, windowHeight);
8 | background(255);
9 |
10 | // CONSTRUCTOR:
11 | foo = new p5.Plot({ left: width*0.2, top: height*0.3, right: width*0.8, bottom: height*0.7});
12 |
13 | foo.plot({ type: 'bar', data: barData, xkey: "x", ykey: "y", strokeweight: 2});
14 | //foo.plot({ type: 'bar', data: barData2, xkey: "x", ykey: "XSUM", strokeweight: 2});
15 | //foo.plot({ type: 'box', data: mpg, xkey: 'year', ykey: 'displ', strokeweight: 2});
16 | //foo.plot({ type: 'box', data: boxData, xkey: 'y', ykey: 'x', strokeweight: 2});
17 |
18 | }
19 |
20 | function draw() {
21 | background(255);
22 | foo.redraw();
23 | }
24 |
--------------------------------------------------------------------------------
/examples/box_plot_example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/box_plot_example/mySketch.js:
--------------------------------------------------------------------------------
1 | var foo; // p5.Plot() object
2 |
3 | var boxData = [{"x":13, "y":"a"}, {"x":16, "y":"a"}, {"x":57, "y":"a"}, {"x":34, "y":"a"}, {"x":26, "y":"a"}, {"x":67, "y":"a"}, {"x":12, "y":"a"},
4 | {"x":45, "y":"b"}, {"x":32, "y":"b"}, {"x":24, "y":"b"}, {"x":86, "y":"b"}, {"x":65, "y":"b"}, {"x":37, "y":"b"}, {"x":98, "y":"b"}];
5 |
6 | function setup() {
7 | createCanvas(windowWidth, windowHeight);
8 | background(255);
9 |
10 | // CONSTRUCTOR:
11 | foo = new p5.Plot({ left: width*0.2, top: height*0.3, right: width*0.8, bottom: height*0.7, background: false});
12 |
13 | foo.plot({ type: 'box', data: economics, xkey: null, ykey: 'pop', strokeweight: 2});
14 | //foo.plot({ type: 'box', data: mpg, xkey: 'year', ykey: 'displ', strokeweight: 2});
15 | //foo.plot({ type: 'box', data: boxData, xkey: 'y', ykey: 'x', strokeweight: 2});
16 |
17 | }
18 |
19 | function draw() {
20 | background(255);
21 | foo.redraw();
22 | }
23 |
--------------------------------------------------------------------------------
/examples/density_plot_example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/density_plot_example/mySketch.js:
--------------------------------------------------------------------------------
1 | var dfile, diamonds; // load from JSON
2 |
3 | var foo; // p5.Plot() object
4 |
5 | function preload() {
6 | dfile = loadStrings('../../support/diamonds.json'); // load the big file
7 | }
8 |
9 | function setup() {
10 | createCanvas(windowWidth, windowHeight);
11 | background(255);
12 |
13 | diamonds = JSON.parse(dfile);
14 | // CONSTRUCTOR:
15 | foo = new p5.Plot({ left: width*0.2, top: height*0.3, right: width*0.8, bottom: height*0.7 });
16 |
17 | // PLOT COMMAND:
18 | // DENSITY
19 | foo.plot({ type: 'density', data: economics, xkey: 'pop', ykey: null, strokeweight: 3, pointdiameter: 5});
20 | }
21 |
22 | function draw() {
23 | background(255);
24 | foo.redraw();
25 | //foo.hover(mouseX, mouseY, 'point');
26 | }
27 |
--------------------------------------------------------------------------------
/examples/dom_control_example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/examples/dom_control_example/mySketch.js:
--------------------------------------------------------------------------------
1 | let foo; // p5.Plot() object
2 | let minBinNum = 2;
3 | let maxBinNum = 30;
4 | let binNum = 2;
5 | let slider;
6 |
7 | function setup(){
8 | createCanvas(windowWidth, windowHeight);
9 | slider = createSlider(minBinNum, maxBinNum, 1);
10 | slider.position(100, 100);
11 | slider.style('width', '80px');
12 | slider.changed(changeBin);
13 | background(255);
14 |
15 | // CONSTRUCTOR:
16 | foo = new p5.Plot({ left: width*0.2, top: height*0.3, right: width*0.8, bottom: height*0.7 });
17 |
18 | // PLOT COMMAND:
19 | // HISTOGRAM
20 | foo.plot({ type: 'histogram', data: economics, xkey: 'pop', strokeweight: 5, bins: binNum});
21 | }
22 |
23 | function draw() {
24 | background(255);
25 | text('current bin number: '+ binNum, 100, 80)
26 | foo.redraw();
27 | foo.hover(mouseX, mouseY, 'bin');
28 | }
29 |
30 | function changeBin(){
31 | binNum = slider.value();
32 | foo.plot({bins: binNum});
33 | }
34 |
--------------------------------------------------------------------------------
/examples/facetingexample/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/facetingexample/mySketch.js:
--------------------------------------------------------------------------------
1 | var survey = [];
2 |
3 | var foo; // p5.Plot() object
4 |
5 | var bar = [{x: 50}, {x: 75}, {x: 33}];
6 |
7 | var a = 0.1;
8 |
9 | function preload() {
10 | }
11 |
12 | function setup() {
13 | createCanvas(windowWidth, windowHeight);
14 | background(255);
15 |
16 | // make a fake survey
17 | for(let i = 0;i<50;i++)
18 | {
19 | var yikes = {};
20 | yikes.q1 = floor(random(6));
21 | yikes.q2 = floor(random(6));
22 | yikes.q3 = floor(random(6));
23 | yikes.q4 = floor(random(6));
24 | yikes.q5 = floor(random(6));
25 |
26 | survey.push(yikes);
27 | }
28 |
29 | console.log(survey);
30 | // CONSTRUCTOR:
31 | //foo = new p5.Plot(); // easy
32 | foo = new p5.Plot({ left: width*0.2, top: height*0.3, right: width*0.8, bottom: height*0.7 });
33 | //foo = new p5.Plot({ left: 100, top: 100, right: 400, bottom: 200, backgroundcolor: 'lightBlue' });
34 | // BAR
35 | //foo.plot({ barwidth: a, type: 'bar2', data: survey, xkey: 'q1', strokeweight: 5});
36 | foo.plot({ type: 'area', data: survey, xkey: ['q1', 'q2', 'q3', 'q4'], ykey:"q5", strokeweight: [1, 2, 3, 4, 5, 6, 7], strokecolor:['red', 'green', 'blue'], fillcolor:['red', 'green', 'blue']});
37 | }
38 |
39 | function draw() {
40 | //background(255);
41 |
42 |
43 | //a = a+.1;
44 | //foo.hover(mouseX, mouseY, 'point');
45 | //foo.hover(mouseX, mouseY, 'bin');
46 | }
47 |
48 | function keyPressed() {
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/examples/firstexample/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/firstexample/mySketch.js:
--------------------------------------------------------------------------------
1 | var dfile, diamonds; // load from JSON
2 |
3 | var foo; // p5.Plot() object
4 |
5 | var mylook = {strokecolor: [255, 0, 255], fillcolor: [0, 255, 0]};
6 | var myotherlook = {strokecolor: [0, 0, 255], fillcolor: [128, 128, 0]};
7 | var mythirdlook = {backgroundcolor: 'Black', gridcolor: 'White'};
8 | var crazygrid = {rows: 50, cols: 50, backgroundcolor: 'Black', gridcolor: 'White'};
9 |
10 | var lukecrap = [{stuff: 50, things: 20}, {stuff: 55, things: 33}, {stuff: 33, things: 45}];
11 | var myData = [{"x":5, "y":10}, {"x":5, "y":10}, {"x":5, "y":10}, {"x":5, "y":10}, {"x":5, "y":10}, {"x":5, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":17, "y":10}, {"x":17, "y":10}, {"x":17, "y":10}, {"x":17, "y":10}, {"x":17, "y":10}];
12 | var boxData = [{"x":13, "y":"a"}, {"x":16, "y":"a"}, {"x":57, "y":"a"}, {"x":34, "y":"a"}, {"x":26, "y":"a"}, {"x":67, "y":"a"}, {"x":12, "y":"a"},
13 | {"x":45, "y":"b"}, {"x":32, "y":"b"}, {"x":24, "y":"b"}, {"x":86, "y":"b"}, {"x":65, "y":"b"}, {"x":37, "y":"b"}, {"x":98, "y":"b"}];
14 | var pieData = [{"x":13, "y":"a"}, {"x":16, "y":"b"}, {"x":57, "y":"c"}, {"x":34, "y":"d"}];
15 |
16 | function preload() {
17 | dfile = loadStrings('../../support/diamonds.json'); // load the big file
18 | //diamonds = loadJSON("https://raw.githubusercontent.com/IDMNYU/p5.js-plot/master/support/diamonds.json");
19 | console.log(diamonds);
20 | }
21 |
22 | var stylelist = [mylook, myotherlook, mythirdlook];
23 | var whichstyle = 0;
24 |
25 | function setup() {
26 | createCanvas(windowWidth, windowHeight);
27 | background(255);
28 |
29 | diamonds = JSON.parse(dfile);
30 | // mix and match:
31 |
32 | // CONSTRUCTOR:
33 | //foo = new p5.Plot(); // easy
34 | foo = new p5.Plot({ left: width*0.2, top: height*0.3, right: width*0.8, bottom: height*0.7 });
35 | //foo = new p5.Plot({ left: 100, top: 100, right: 400, bottom: 200, backgroundcolor: 'lightBlue' });
36 |
37 | //noLoop();
38 | background(255);
39 | // PLOT COMMAND:
40 | // LINE
41 | //foo.plot({data: mpg, xkey: 'year', ykey: 'displ', strokeweight: 5}); // default line
42 | //foo.plot({type: 'line', data: lukecrap, xkey: 'stuff', ykey: 'things'});
43 | //foo.plot({ type: 'line', data: economics, xkey: 'pop', ykey: 'unemploy', strokeweight: 5 }, stylelist[whichstyle]);
44 |
45 | // POINT
46 | //foo.plot({type: 'point', data: mpg, xkey: 'year', ykey: 'displ', strokeweight: 5});
47 | //foo.plot({type: 'point', data: lukecrap, xkey: 'stuff', ykey: 'things', strokeweight: 5}, stylelist[whichstyle]);
48 | //foo.plot({ type: 'point', data: economics, xkey: 'pop', ykey: 'unemploy', strokeweight: 5 }, stylelist[whichstyle]);
49 | //foo.plot({ type: 'point', data: mpg, xkey: 'cty', ykey: 'hwy'});
50 | foo.plot({ type: 'point', data: diamonds, xkey: 'carat', ykey: 'price', strokecolor: [255, 0, 0, 32], fillcolor: [128, 128, 255, 32] });
51 | //foo.plot({ type: 'point', data: diamonds, xkey: 'carat', ykey: 'price', strokecolor: [255, 0, 0, 32], fillcolor: [128, 128, 255, 32] });
52 | //foo.plot({ type: 'point', data: diamonds, xkey: 'carat', ykey: 'price', strokecolor: [255, 0, 0, 32], fillcolor: [128, 128, 255, 32] }, crazygrid);
53 |
54 | // AREA
55 | //foo.plot({ type: 'area', data: economics, xkey: 'pop', ykey: 'unemploy', strokeweight: 5 }, stylelist[whichstyle]); // custom look
56 |
57 | // HISTOGRAM
58 | //foo.plot({ type: 'histogram', data: economics, xkey: 'pop', strokeweight: 5});
59 |
60 | // PIE
61 | //foo.plot({type: 'pie', data: pieData, xkey:'x', background: false});
62 |
63 | // not yet.....................................................................
64 | // BOX
65 | //foo.plot({ type: 'box', data: economics, xkey: 'pop', strokeweight: 5});
66 | //foo.plot({ type: 'box', data: mpg, xkey: 'displ', ykey: 'year', strokeweight: 5});
67 | //foo.plot({ type: 'box', data: diamonds, xkey: 'price', ykey: 'clarity', strokeweight: 1});
68 | //foo.plot({ type: 'box', data: boxData, xkey: 'x', ykey: 'y', strokeweight: 5});
69 |
70 | // DENSITY
71 | //foo.plot({ type: 'density', data: economics, xkey: 'pop', strokeweight: 5});
72 |
73 |
74 |
75 | }
76 |
77 | function draw() {
78 | background(255);
79 | foo.redraw();
80 | foo.hover(mouseX, mouseY, 'point');
81 | //foo.hover(mouseX, mouseY, 'bin');
82 | }
83 |
84 | function keyPressed() {
85 | whichstyle = (whichstyle+1)%stylelist.length;
86 | foo.plot(stylelist[whichstyle]);
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/examples/secondexample/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/secondexample/mySketch.js:
--------------------------------------------------------------------------------
1 | var dfile, diamonds; // load from JSON
2 |
3 | var foo; // p5.Plot() object
4 |
5 | function preload() {
6 | }
7 |
8 | function setup() {
9 | createCanvas(windowWidth, windowHeight);
10 | background(255);
11 |
12 | // CONSTRUCTOR:
13 | //foo = new p5.Plot(); // easy
14 | foo = new p5.Plot({ left: width*0.2, top: height*0.3, right: width*0.8, bottom: height*0.7 });
15 | //foo = new p5.Plot({ left: 100, top: 100, right: 400, bottom: 200, backgroundcolor: 'lightBlue' });
16 |
17 | background(255);
18 | //foo.plot({ type: 'point', data: mpg, xkey: 'cty', ykey: 'hwy', strokecolor: [255, 0, 0, 32], fillcolor: [128, 128, 255, 32] });
19 |
20 |
21 | // AREA
22 | //foo.plot({ type: 'area', data: economics, xkey: 'pop', ykey: 'unemploy', strokeweight: 5 }, stylelist[whichstyle]); // custom look
23 |
24 | // HISTOGRAM
25 | foo.plot({ type: 'histogram', data: mpg, xkey: 'trans', strokeweight: 5});
26 |
27 | // PIE
28 | //foo.plot({type: 'pie', data: pieData, xkey:'x', background: false});
29 |
30 | // not yet.....................................................................
31 | // BOX
32 | //foo.plot({ type: 'box', data: economics, xkey: 'pop', strokeweight: 5});
33 | //foo.plot({ type: 'box', data: mpg, xkey: 'displ', ykey: 'year', strokeweight: 5});
34 | //foo.plot({ type: 'box', data: diamonds, xkey: 'price', ykey: 'clarity', strokeweight: 1});
35 | //foo.plot({ type: 'box', data: boxData, xkey: 'x', ykey: 'y', strokeweight: 5});
36 |
37 | // DENSITY
38 | //foo.plot({ type: 'density', data: economics, xkey: 'pop', strokeweight: 5});
39 |
40 |
41 |
42 | }
43 |
44 | function draw() {
45 | background(255);
46 | foo.redraw();
47 | foo.hover(mouseX, mouseY, 'point');
48 | //foo.hover(mouseX, mouseY, 'bin');
49 | }
50 |
51 | function keyPressed() {
52 | whichstyle = (whichstyle+1)%stylelist.length;
53 | foo.plot(stylelist[whichstyle]);
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/examples/simplearraytest/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/simplearraytest/mySketch.js:
--------------------------------------------------------------------------------
1 | var foo; // p5.Plot() object
2 |
3 | var mylook = {strokecolor: [255, 0, 255], fillcolor: [0, 255, 0]};
4 |
5 | var d = [{stuff: 50, things: 20}, {stuff: 55, things: 33}, {stuff: 33, things: 45}];
6 | var e = [-1, 0, 10, 50, -33, 2.5, 0];
7 |
8 | function setup() {
9 | createCanvas(windowWidth, windowHeight);
10 | background(255);
11 |
12 | // CONSTRUCTOR:
13 | foo = new p5.Plot({left: width*0.2, top: height*0.3, right: width*0.8, bottom: height*0.7});
14 |
15 | //noLoop();
16 | background(255);
17 |
18 | // PLOT COMMAND:
19 | // LINE
20 | foo.plot({ type: 'line', data: e});
21 | }
22 |
23 | function draw() {
24 | background(255);
25 | foo.redraw();
26 | foo.hover(mouseX, mouseY, 'point');
27 | }
28 |
--------------------------------------------------------------------------------
/examples/simplesvg_barexample/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/examples/simplesvg_barexample/mySketch.js:
--------------------------------------------------------------------------------
1 | // test bar1
2 | //let myData = [{letter:'a'},{letter:'a'},{letter:'a'},{letter:'a'},{letter:'b'},{letter:'b'},{letter:'c'},{letter:'c'},{letter:'c'}];
3 | //let myData = ['a', 'a', 'a', 'b', 'b', 'donut'];
4 |
5 | // test bar2
6 | let myData = [{letter:'a', amt:10},{letter:'a', amt:5},{letter:'a',amt:10},{letter:'b', amt:50},{letter:'b',amt:10},{letter:'c',amt:5},{letter:'c',amt:5},{letter:'c',amt:5}];
7 |
8 | let foo;
9 | let myPlot;
10 |
11 |
12 | function setup(){
13 | createCanvas(800, 400);
14 |
15 | background(255, 0, 0);
16 | //console.log(myData);
17 |
18 | foo = new p5.Plot({data: myData, fillcolor: [180, 50, 50, 100], type: ['bar2'], width: 500, height: 250});
19 | myPlot = foo.plot();
20 | }
21 |
22 | function draw() {
23 | background(200);
24 | text(frameRate().toFixed(2), width-50, 50);
25 | foo.draw(0, 0, width, height);
26 | }
27 |
--------------------------------------------------------------------------------
/examples/simplesvg_boxexample/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/examples/simplesvg_boxexample/mySketch.js:
--------------------------------------------------------------------------------
1 | // test box plot
2 | // discrete x, continues y
3 |
4 | //let myData = [{"fruit":"apple", "num":13}, {"fruit":"apple", "num":16}, {"fruit":"apple", "num":57}, {"fruit":"apple", "num":34}, {"fruit":"apple", "num":26}, {"fruit":"apple", "num":67}, {"fruit":"apple", "num":12}, {"fruit":"banana", "num":45}, {"fruit":"banana", "num":32}, {"fruit":"banana", "num":24}, {"fruit":"banana", "num":86}, {"fruit":"banana", "num":65}, {"fruit":"banana", "num":37}, {"fruit":"banana", "num":98}];
5 |
6 | // just a set of numbers
7 | let myData = [13, 16, 57, 87, 92, 10, 120, 30, 72, 101];
8 |
9 | let foo;
10 | let myPlot;
11 |
12 |
13 | function setup(){
14 | createCanvas(800, 400);
15 |
16 | background(255, 0, 0);
17 | //console.log(myData);
18 |
19 | //foo = new p5.Plot({data: myData, xkey: 'fruit', ykey: 'num', strokecolor: [180, 50, 50, 200], type: ['box'], width: 500, height: 250});
20 | foo = new p5.Plot({data: myData, strokecolor: [180, 50, 50, 200], type: ['box'], width: 500, height: 250});
21 | myPlot = foo.plot();
22 | }
23 |
24 | function draw() {
25 | background(200);
26 | text(frameRate().toFixed(2), width-50, 50);
27 | foo.draw(0, 0, width, height);
28 | }
29 |
--------------------------------------------------------------------------------
/examples/simplesvg_example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/examples/simplesvg_example/mySketch.js:
--------------------------------------------------------------------------------
1 | let earthquakes;
2 | let myData = [];
3 | let foo;
4 | let x = -100;
5 | let y = 100;
6 |
7 | let myPlot;
8 |
9 | function preload(){
10 | earthquakes = loadJSON('https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson');
11 |
12 | }
13 |
14 | function setup(){
15 | createCanvas(800, 400);
16 |
17 | background(255, 0, 0);
18 | for (let i=0; i< earthquakes.features.length; i++){
19 | let lat = earthquakes.features[i].geometry.coordinates[0];
20 | let long = earthquakes.features[i].geometry.coordinates[1];
21 | myData.push({lat, long});
22 | }
23 | //console.log(myData);
24 |
25 | // CONSTRUCTOR:
26 | console.log(colorMode()._colorMaxes);
27 | //colorMode(RGB);
28 | colorMode(HSL);
29 | foo = new p5.Plot({data: myData, fillcolor: [180, 50, 50, 1], type: ['point', 'line'], xkey: 'lat', ykey: 'long', width: 500, height: 250});
30 | myPlot = foo.plot();
31 | }
32 |
33 | function draw() {
34 | //background(random()*255, random()*255, random()*255);
35 | background(200);
36 | text(frameRate().toFixed(2), width-50, 50);
37 | //x-=10;
38 | //y+=10;
39 | // tint(0, 255, 0);
40 | // rect(0, 0, mouseX, mouseY);
41 | // foo.draw(0, 0, mouseX, mouseY);
42 | //rect(0, 0, width, height);
43 | foo.draw(0, 0, width, height);
44 |
45 | fill(255, 255, 255, 150);
46 | ellipse(width/2, height/2, 200, 200);
47 |
48 | //myData.push({lat:x,long:y});
49 |
50 | //mydiv.position(mouseX, mouseY);
51 | //console.log(foo.plotData);
52 | }
53 |
54 | function keyTyped() {
55 | myData.push({lat:random(foo._xmin, foo._xmax),long:random(foo._ymin, foo._ymax)});
56 | foo.data = myData;
57 | }
58 |
--------------------------------------------------------------------------------
/examples/testexample/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/examples/testexample/mySketch.js:
--------------------------------------------------------------------------------
1 | var dfile, diamonds; // load from JSON
2 |
3 | var foo; // p5.Plot() object
4 |
5 | var mylook = {strokecolor: [255, 0, 255], fillcolor: [0, 255, 0]};
6 | var myotherlook = {strokecolor: [0, 0, 255], fillcolor: [128, 128, 0]};
7 | var mythirdlook = {backgroundcolor: 'Black', gridcolor: 'White'};
8 | var crazygrid = {rows: 50, cols: 50, backgroundcolor: 'Black', gridcolor: 'White'};
9 |
10 | var lukecrap = [{stuff: 50, things: 20}, {stuff: 55, things: 33}, {stuff: 33, things: 45}];
11 | var myData = [{"x":5, "y":10}, {"x":5, "y":10}, {"x":5, "y":10}, {"x":5, "y":10}, {"x":5, "y":10}, {"x":5, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":10, "y":10}, {"x":17, "y":10}, {"x":17, "y":10}, {"x":17, "y":10}, {"x":17, "y":10}, {"x":17, "y":10}];
12 | var boxData = [{"x":13, "y":"a"}, {"x":16, "y":"a"}, {"x":57, "y":"a"}, {"x":34, "y":"a"}, {"x":26, "y":"a"}, {"x":67, "y":"a"}, {"x":12, "y":"a"},
13 | {"x":45, "y":"b"}, {"x":32, "y":"b"}, {"x":24, "y":"b"}, {"x":86, "y":"b"}, {"x":65, "y":"b"}, {"x":37, "y":"b"}, {"x":98, "y":"b"}];
14 | var pieData = [{"x":13, "y":"a"}, {"x":16, "y":"b"}, {"x":57, "y":"c"}, {"x":34, "y":"d"}];
15 |
16 | function preload() {
17 | dfile = loadStrings('diamonds.json'); // load the big file
18 | }
19 |
20 | var stylelist = [mylook, myotherlook, mythirdlook];
21 | var whichstyle = 0;
22 |
23 | function setup() {
24 | createCanvas(windowWidth, windowHeight);
25 | background(255);
26 |
27 | diamonds = JSON.parse(dfile);
28 | // mix and match:
29 |
30 | // CONSTRUCTOR:
31 | //foo = new p5.Plot(); // easy
32 | foo = new p5.Plot({ left: width*0.2, top: height*0.3, right: width*0.8, bottom: height*0.7 });
33 | //foo = new p5.Plot({ left: 100, top: 100, right: 400, bottom: 200, backgroundcolor: 'lightBlue' });
34 |
35 | //noLoop();
36 | background(255);
37 | // PLOT COMMAND:
38 | // LINE
39 | //foo.plot({data: mpg, xkey: 'year', ykey: 'displ', strokeweight: 5}); // default line
40 | //foo.plot({type: 'line', data: lukecrap, xkey: 'stuff', ykey: 'things'});
41 | foo.plot({ type: 'line', data: economics, xkey: 'pop', ykey: 'unemploy', strokeweight: 5 }, stylelist[whichstyle]);
42 |
43 | // POINT
44 | //foo.plot({type: 'point', data: mpg, xkey: 'year', ykey: 'displ', strokeweight: 5});
45 | //foo.plot({type: 'point', data: lukecrap, xkey: 'stuff', ykey: 'things', strokeweight: 5}, stylelist[whichstyle]);
46 | //foo.plot({ type: 'point', data: economics, xkey: 'pop', ykey: 'unemploy', strokeweight: 5 }, stylelist[whichstyle]);
47 | //foo.plot({ type: 'point', data: mpg, xkey: 'cty', ykey: 'hwy'});
48 | //foo.plot({ type: 'point', data: diamonds, xkey: 'carat', ykey: 'price', strokecolor: [255, 0, 0, 32], fillcolor: [128, 128, 255, 32] });
49 | //foo.plot({ type: 'point', data: diamonds, xkey: 'carat', ykey: 'price', strokecolor: [255, 0, 0, 32], fillcolor: [128, 128, 255, 32] });
50 | //foo.plot({ type: 'point', data: diamonds, xkey: 'carat', ykey: 'price', strokecolor: [255, 0, 0, 32], fillcolor: [128, 128, 255, 32] }, crazygrid);
51 |
52 | // AREA
53 | //foo.plot({ type: 'area', data: economics, xkey: 'pop', ykey: 'unemploy', strokeweight: 5 }, stylelist[whichstyle]); // custom look
54 |
55 | // HISTOGRAM
56 | //foo.plot({ type: 'histogram', data: economics, xkey: 'pop', strokeweight: 5});
57 |
58 | // PIE
59 | //foo.plot({type: 'pie', data: pieData, xkey:'x', background: false});
60 |
61 | // not yet.....................................................................
62 | // BOX
63 | //foo.plot({ type: 'box', data: economics, xkey: 'pop', strokeweight: 5});
64 | //foo.plot({ type: 'box', data: mpg, xkey: 'displ', ykey: 'year', strokeweight: 5});
65 | //foo.plot({ type: 'box', data: diamonds, xkey: 'price', ykey: 'clarity', strokeweight: 1});
66 | //foo.plot({ type: 'box', data: boxData, xkey: 'x', ykey: 'y', strokeweight: 5});
67 |
68 | // DENSITY
69 | //foo.plot({ type: 'density', data: economics, xkey: 'pop', strokeweight: 5});
70 |
71 |
72 |
73 | }
74 |
75 | function draw() {
76 | background(255);
77 | foo.redraw();
78 | foo.hover(mouseX, mouseY, 'point');
79 | //foo.hover(mouseX, mouseY, 'bin');
80 | }
81 |
82 | function keyPressed() {
83 | whichstyle = (whichstyle+1)%stylelist.length;
84 | foo.plot(stylelist[whichstyle]);
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/ggplot2-cheatsheet.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDMNYU/p5.js-plot/6b4c0ab6e1e1a8bf4a302d175067026ef127113a/ggplot2-cheatsheet.pdf
--------------------------------------------------------------------------------
/lib/p5.plot.js:
--------------------------------------------------------------------------------
1 | // p5.Plot
2 | // "grammar of graphics" influenced data viz for p5.js
3 | // creative coding summer vibes team, NYU IDM, 2018
4 | //
5 |
6 |
7 | // the plan should be
8 | // the constructor lets you set up whatever parameters you want
9 | // but won't render anything
10 | // plot() renders to a p5.createGraphics
11 | // redraw() plunks down the p5.graphics context already plot()'ed
12 | // hover() draws the fucker on top of the graphics context
13 |
14 | // the usual craziness:
15 | (function (root, factory) {
16 | if (typeof define === 'function' && define.amd)
17 | define('p5.func', ['p5'], function (p5) { (factory(p5));});
18 | else if (typeof exports === 'object')
19 | factory(require('../p5'));
20 | else
21 | factory(root['p5']);
22 | }(this, function (p5) {
23 |
24 | //
25 | // start real stuff
26 | //
27 |
28 | // new style:
29 | p5.Plot = class {
30 |
31 | // this runs when you instantiate:
32 | // (also contains property defaults)
33 | constructor (_args) {
34 | //
35 | // defaults:
36 | //
37 | this.backgroundcolor = 'Cornsilk';
38 | this.gridcolor = 'DarkSlateBlue';
39 | this.gridweight = 4;
40 | this._fillcolor = ['WhiteSmoke'];
41 | this._strokecolor = ['DarkRed'];
42 | this._strokeweight = [1];
43 | this.pointdiameter = 20;
44 | this.background = true;
45 | this.type = 'line'; // type of plot
46 | this.stat = 'bin'; // statistical transformation for 1-var plots
47 | this.bins = 30; // number of slices in binning plots
48 | //this._bins = 30; // does bin number change when faceting?
49 | this.xlabel = 'x'; // axis label
50 | this.ylabel = 'y'; // axis label
51 | this.xlabelvisible = true;
52 | this.ylabelvisible = true;
53 | this.cols = 5;
54 | this.rows = 5;
55 | this.left = 0;
56 | this.top = 0;
57 | this.right = width;
58 | this.bottom = height;
59 | this.data = {};
60 | //this.xkey = ""; // key value for x axis
61 | //this.ykey = ""; // key value for y axis
62 | this._xkey = [];
63 | this._ykey = [];
64 | //this.pd = 1; // pixeldensity
65 | this.barpct = 0.5;
66 |
67 | this.typelist = {};
68 |
69 | // function definitions
70 | this.typelist.line = { // 1 continuous
71 | // continuous function x y
72 | xtype: 'continuous',
73 | ytype: 'continuous',
74 | function: this.drawLineGraph
75 | };
76 |
77 | this.typelist.point = { // continuous x, continuous y
78 | xtype: 'continuous',
79 | ytype: 'continuous',
80 | function: this.drawPointGraph
81 | };
82 |
83 | this.typelist.area = { // 1 continuous
84 | // continuous function x y
85 | xtype: 'continuous',
86 | ytype: 'continuous',
87 | function: this.drawAreaGraph
88 | };
89 |
90 | this.typelist.density = { // 1 continuous
91 | xtype: 'continuous',
92 | ytype: 'none',
93 | function: this.drawDensityGraph
94 | };
95 |
96 | this.typelist.box = { // discrete x, continuous y
97 | xtype: 'discrete',
98 | ytype: 'continuous',
99 | function: this.drawBoxPlot
100 | };
101 |
102 | this.typelist.histogram = { // 1 continuous variable
103 | xtype: 'continuous',
104 | ytype: 'none',
105 | function: this.drawHistogram
106 | };
107 |
108 | this.typelist.bar = { // discrete x, continuous y
109 | xtype: 'discrete',
110 | ytype: 'continuous',
111 | function: this.drawBar
112 | };
113 |
114 | this.typelist.bar2 = { // discrete x, continuous y
115 | xtype: 'discrete',
116 | ytype: 'none',
117 | function: this.drawBar2
118 | };
119 |
120 | this.typelist.pie = {
121 | xtype: 'discrete',
122 | ytype: 'continuous',
123 | function: this.drawPieChart
124 | };
125 |
126 |
127 | //get strokecolor () { return this._strokecolor};
128 | //
129 | // end defaults
130 | //
131 |
132 | // internals:
133 | this._xmin; // internal
134 | this._xmax; // internal
135 | this._ymin; // internal
136 | this._ymax; // internal
137 |
138 | // integrate arguments:
139 | // this is an awesome ES6 hack where the Object.assign()
140 | // method lets you splice shit from one Object literal into
141 | // another Object, just replacing whatever's there.
142 | for(let i in arguments)
143 | {
144 | Object.assign(this, arguments[i]);
145 | }
146 |
147 | push();
148 | this.graphics = createGraphics((this.right-this.left), (this.bottom-this.top));
149 | pop();
150 | //this.graphics.pixelDensity(this.pd);
151 |
152 | this.plotData = []; // create a new dataset to workwith instead of changing the original!!!!!!!!!!!!
153 | console.log('p5 plot!');
154 |
155 | }; // end of constructor
156 |
157 | // setters:
158 | set fillcolor (fillcolor) {
159 | this._fillcolor = Array.isArray(fillcolor) ? fillcolor : [fillcolor];
160 | };
161 | set strokecolor (strokecolor) {
162 | this._strokecolor = Array.isArray(strokecolor) ? strokecolor : [strokecolor];
163 | };
164 | set strokeweight (strokeweight) {
165 | this._strokeweight = Array.isArray(strokeweight) ? strokeweight : [strokeweight];
166 | };
167 | set xkey (xkey) {
168 | this._xkey = Array.isArray(xkey) ? xkey : [xkey];
169 | };
170 | set ykey (ykey) {
171 | this._ykey = Array.isArray(ykey) ? ykey : [ykey];
172 | };
173 |
174 | set barwidth(_v) // bar percentage
175 | {
176 | this.barpct = constrain(_v, 0, 1);
177 | };
178 |
179 | // MAIN PLOTTER FUNCTION
180 | //
181 | plot (_args) {
182 |
183 | // integrate arguments (see above):
184 | for(let i in arguments)
185 | {
186 | Object.assign(this, arguments[i]);
187 | }
188 |
189 | this.parseData(); // figure out min and max scalings, etc.
190 |
191 | this.graphics.clear();
192 |
193 | // draw a background?
194 | if(this.background) this.drawBackground();
195 |
196 | // which graph style?
197 | this.typelist[this.type].function(this);
198 |
199 | this.redraw();
200 | }; // END OF MAIN PLOTTER FUNCTION
201 |
202 | //
203 | // DRAW A BACKGROUND
204 | //
205 | drawBackground(){
206 | this.graphics.push();
207 | // this.graphics.scale(1/this.pd);
208 | // dont need bg rect anymore cuz graphics is a new canvas
209 | this.graphics.background(this.backgroundcolor);
210 |
211 | this.graphics.stroke(this.gridcolor);
212 | this.graphics.strokeWeight(this.gridweight);
213 |
214 | // map one more line than given
215 | // vertical lines
216 | for(let i = 0;i=this.plotData[i]._hoverx &&
257 | _x<=this.plotData[i]._hoverx+this.plotData[i]._hoverw &&
258 | _y>=this.plotData[i]._hovery &&
259 | _y<=this.plotData[i]._hovery+this.plotData[i]._hoverh)
260 | {
261 | hitme = i;
262 | break;
263 | }
264 | }
265 | }
266 | // PART 2 - DO THE HOVER
267 | if(hitme>-1)
268 | {
269 | push();
270 | var bgc = color(this.backgroundcolor);
271 | bgc.setAlpha(100);
272 | fill(bgc);
273 | var fgc = color(this.strokecolor);
274 | fgc.setAlpha(255);
275 | stroke(fgc);
276 | rect(_x, _y, 200, 100);
277 | noStroke();
278 | fill(fgc);
279 | textSize(12);
280 |
281 | if(_hittype=='point') {
282 | text("DATA:", this.plotData[hitme]._hoverx+10, this.plotData[hitme]._hovery+20);
283 | text(this.xkey + ": " + this.plotData[hitme][this.xkey], this.plotData[hitme]._hoverx+10, this.plotData[hitme]._hovery+40);
284 | text(this.ykey + ": " + this.plotData[hitme][this.ykey], this.plotData[hitme]._hoverx+10, this.plotData[hitme]._hovery+60);
285 | }
286 | else if(_hittype=='bin') {
287 | // highlight bin
288 | text("Bin "+ (hitme+1), _x+10, _y+20)
289 | text("Frequency: " + this.plotData[hitme].freq, _x+10, _y+40);
290 | text("Range: " + this.plotData[hitme].minBound +" to "+this.plotData[hitme].maxBound, _x+10, _y+60);
291 | push();
292 | noFill();
293 | stroke(0);
294 | strokeWeight(this.strokeweight);
295 | rect(this.plotData[hitme]._hoverx, this.plotData[hitme]._hovery, this.plotData[hitme]._hoverw, this.plotData[hitme]._hoverh)
296 | pop();
297 | }
298 | pop();
299 | }
300 | }
301 |
302 | //
303 | // parseData() - MAKE SENSE OF THE DATASET
304 | //
305 | parseData() {
306 | // STEP ONE:
307 | // what happens if the data array is not made up of object literals
308 |
309 | // simple array test:
310 | if(Array.isArray(this.data) && typeof(this.data[0])==="number")
311 | {
312 | var _newdata = this.tokenize(this.data); // fix
313 | this.data = _newdata; // swap
314 | }
315 | // STEP TWO:
316 | // fix if we have no xkey / ykey defined
317 | if(this._xkey.length==0){
318 | this._xkey = [Object.keys(this.data[0])[0]];
319 | }
320 | if(this._ykey.length==0){
321 | this._ykey = [Object.keys(this.data[0])[1]];
322 | }
323 |
324 | console.log('_xkey', this._xkey, '_ykey', this._ykey);
325 |
326 | // STEP THREE:
327 | // make sure the keys are the right type
328 | console.log(this.typelist[this.type].xtype + " " + this.typelist[this.type].ytype);
329 |
330 | // & faceting
331 | /* old method
332 | if (Array.isArray(this.xkey)){
333 | this._xmin = this.data[0][this.xkey[0]];
334 | this._xmax = this.data[0][this.xkey[0]];
335 | }
336 | else{
337 | this._xmin = this.data[0][this.xkey];
338 | this._xmax = this.data[0][this.xkey];
339 | }
340 | if (Array.isArray(this.ykey)){
341 | this._ymin = this.data[0][this.ykey[0]];
342 | this._ymax = this.data[0][this.ykey[0]];
343 | }
344 | else{
345 | this._ymin = this.data[0][this.ykey];
346 | this._ymax = this.data[0][this.ykey];
347 | }
348 | */
349 |
350 | this._xmin = this.data[0][this._xkey[0]];
351 | this._xmax = this.data[0][this._xkey[0]];
352 | this._ymin = this.data[0][this._ykey[0]];
353 | this._ymax = this.data[0][this._ykey[0]];
354 |
355 | /* old method
356 | for(let i=0;ithis._xmax) this._xmax = this.data[i][this.xkey[j]];
363 | currentData[this.xkey[j]] = this.data[i][this.xkey[j]];
364 | }
365 | // min and max of total
366 | }
367 | else{
368 | if(this.data[i][this.xkey]this._xmax) this._xmax = this.data[i][this.xkey];
370 | currentData[this.xkey] = this.data[i][this.xkey];
371 | }
372 |
373 | // ykey
374 | if (Array.isArray(this.ykey)){ // ykey is array
375 | for (let i=0; ithis._ymax) this._ymax = this.data[i][this.ykey[j]];
378 | currentData[this.ykey[i]] = this.data[i][this.ykey[i]];
379 | }
380 | }
381 | else{
382 | if(this.data[i][this.ykey]this._ymax) this._ymax = this.data[i][this.ykey];
384 | currentData[this.ykey] = this.data[i][this.ykey];
385 | }
386 | this.plotData.push(currentData);
387 | }
388 | */
389 |
390 | for(let i=0;ithis._xmax) this._xmax = this.data[i][this._xkey[j]];
396 | currentData[this._xkey[j]] = this.data[i][this._xkey[j]];
397 | }
398 |
399 | // ykey
400 | for (let k=0; kthis._ymax) this._ymax = this.data[i][this._ykey[k]];
403 | currentData[this._ykey[k]] = this.data[i][this._ykey[k]];
404 | }
405 |
406 | // data we actually use
407 | this.plotData.push(currentData);
408 | }
409 | } // end of parseData
410 |
411 | //
412 | //
413 | // SORT AN ARRAY BASED ON A KEY
414 | //
415 | sortData(_key) {
416 | // sort by xkey
417 | this.data.sort(function(a, b) {
418 | return a[_key] - b[_key];
419 | });
420 |
421 | this.plotData.sort(function(a, b) {
422 | return a[_key] - b[_key];
423 | });
424 | }
425 |
426 | //
427 | // TOKENIZE - utility to JSONify a simple array
428 | //
429 | tokenize(_arr) {
430 | var a = [];
431 | for(var i in _arr)
432 | {
433 | var j = {};
434 | j.index = i;
435 | j.value = _arr[i];
436 | a.push(j);
437 | }
438 | return(a);
439 | }
440 |
441 | //
442 | // LINE GRAPH
443 | //
444 | drawLineGraph(that) {
445 | console.log('Line Graph!');
446 |
447 | /*
448 | let plotxArr = new Array(that.plotData.length);
449 | let plotyArr = new Array(that.plotData.length);
450 | let hoverxArr = new Array(that.plotData.length);
451 | let hoveryArr = new Array(that.plotData.length);
452 |
453 | for (let k = 0; k < that.plotData.length; k++) {
454 | plotxArr[k] = new Array(that.xkey.length);
455 | plotyArr[k] = new Array(that.xkey.length);
456 | hoverxArr[k] = new Array(that.xkey.length);
457 | hoveryArr[k] = = new Array(that.xkey.length);
458 | }
459 | */
460 |
461 | that.graphics.push();
462 | // need to figure out a way to do this for all graphs
463 | // faceting: multiple xkeys
464 | // iterate through all x keys
465 | console.log(that._xkey.length);
466 |
467 | // what happens when multiple xkeys and ykeys?
468 | for (let i=0; i= currentMinBound) && (currentValue maxFreq){
703 | maxFreq = currentFreq;
704 | }
705 | }
706 |
707 | that.graphics.push();
708 |
709 | that.graphics.fill(that.fillcolor);
710 | that.graphics.stroke(that.strokecolor);
711 | that.graphics.strokeWeight(that.strokeweight);
712 |
713 | // okay, so here if we want to have a hover function, and a plotData,
714 | // the plotData should just have the length of the bins
715 | // we need to at least store 4 hover values:
716 | // _hoverx _hovery, _hoverw, hoverh
717 | // for plot values, also 4
718 | // I'm just gonna reset plotData to empty here
719 | that.plotData = binArr;
720 |
721 | // start to draw rectangles!!!
722 | that.graphics.rectMode(CORNER); // x, y, w, h
723 | let drawWidth = (that.right-that.left)/numBins; // width of each rect
724 | let currentX = 0; // in graphics, start with 0
725 | for (let p=0; pvalueMax){
904 | valueMax = that.data[k][ykey];
905 | }
906 | }
907 |
908 | let yQuartileBoundsArr = that.quartileBounds(valueArr);
909 | // map minimum, first quartile, median, third quartile, and maximum into the graph
910 | // two graphs should have a common scale instead of their own scale
911 | let boxMin = map(yQuartileBoundsArr[0], valueMin, valueMax, 0, that.graphics.width);
912 | let boxQ1 = map(yQuartileBoundsArr[1], valueMin, valueMax, 0, that.graphics.width);
913 | let boxMedian = map(yQuartileBoundsArr[2], valueMin, valueMax, 0, that.graphics.width);
914 | let boxQ3 = map(yQuartileBoundsArr[3], valueMin, valueMax, 0, that.graphics.width);
915 | let boxMax = map(yQuartileBoundsArr[4], valueMin, valueMax, 0, that.graphics.width);
916 |
917 | console.log(boxMin+' '+boxQ1+' '+boxMedian+' '+boxQ3+' '+ boxMax);
918 |
919 | // graph multiple horizontal box plots after dealing with data
920 |
921 | // the height of box, keep it constant
922 | //let boxHeight = this.bottom-this.top;
923 |
924 | that.drawOneBox(boxMin, boxQ1, boxMedian, boxQ3, boxMax, boxY, boxHeight);
925 |
926 | //draw next box, the Y pos will increase!
927 | boxY += boxMargin + boxHeight;
928 | }
929 | that.graphics.pop();
930 | }
931 |
932 |
933 |
934 | // find the median
935 | // if array is odd number, median is middle number
936 | // if array is even number, median is middle two numbers added then divide by two
937 | getMedian(sampleArr){
938 | sampleArr.sort(function(a, b){return a - b});
939 | // even
940 | if (sampleArr.length%2 === 0){
941 | let numA = sampleArr[sampleArr.length/2 - 1];
942 | let numB = sampleArr[sampleArr.length/2];
943 | return (numA + numB)/2;
944 | }
945 | // odd
946 | else{
947 | return sampleArr[(sampleArr.length - 1)/2];
948 | }
949 | }
950 |
951 | // find medians and quartiles
952 | quartileBounds(sampleArr){
953 | // must sort array first
954 | sampleArr.sort(function(a, b){return a - b});
955 | let _firstHalf;
956 | let _secondHalf;
957 | // even
958 | if (sampleArr.length%2 === 0){
959 | _firstHalf = sampleArr.slice(0, sampleArr.length/2);
960 | _secondHalf = sampleArr.slice(sampleArr.length/2, sampleArr.length);
961 | }
962 | // odd
963 | else {
964 | _firstHalf = sampleArr.slice(0, (sampleArr.length-1)/2);
965 | _secondHalf = sampleArr.slice(((sampleArr.length-1)/2)+1, sampleArr.length);
966 | }
967 | let _0percent = min(sampleArr);
968 |
969 | // find the medians for each split
970 | let _25percent = this.getMedian(_firstHalf);
971 | let _75percent = this.getMedian(_secondHalf);
972 |
973 | let _50percent = this.getMedian(sampleArr);
974 | let _100percent = max(sampleArr);
975 |
976 | return [ _0percent, _25percent, _50percent, _75percent, _100percent];
977 | }
978 |
979 | drawOneBox(boxMin, boxQ1, boxMed, boxQ3, boxMax, boxY, boxHeight){
980 | this.graphics.line(boxMin, boxY+boxHeight/4, boxMin, boxY+boxHeight/4+boxHeight/2); // minimum
981 |
982 | this.graphics.line(boxQ1, boxY, boxQ1, boxY+boxHeight); // Q1
983 |
984 | this.graphics.line(boxMed, boxY, boxMed, boxY+boxHeight); // median
985 |
986 | this.graphics.line(boxQ3, boxY, boxQ3, boxY+boxHeight); // Q3
987 |
988 | this.graphics.line(boxMax, boxY+boxHeight/4, boxMax, boxY+boxHeight/4+boxHeight/2); //maximum
989 |
990 | // connect
991 | this.graphics.line(boxQ1, boxY, boxQ3, boxY); // top of box
992 | this.graphics.line(boxQ1, boxY+boxHeight, boxQ3, boxY+boxHeight); // bot of box
993 | this.graphics.line(boxMin, boxY+boxHeight/2, boxQ1, boxY+boxHeight/2);
994 | this.graphics.line(boxQ3, boxY+boxHeight/2, boxMax, boxY+boxHeight/2);
995 | }
996 |
997 | //
998 | // DENSITY GRAPH
999 | //
1000 | drawDensityGraph(that){
1001 | // density graph is taking one contineous variable
1002 | // here we assume a bin is given, !!!!!!!!!!!!but possibly no bin and discrete data is given!!!!!!!!!
1003 | // mapping frequencies within each bin
1004 | // find the percentage of the frequency
1005 |
1006 | // here let's assume we only take xkey
1007 | let xkey = that.xkey;
1008 | //let ykey = that.ykey;
1009 |
1010 | let xmin = that._xmin;
1011 | let xmax = that._xmax;
1012 | //let ymin = that._ymin;
1013 | //let ymax = that._ymax;
1014 |
1015 | let numBins = that.bins;
1016 | let binRange = (xmax-xmin)/numBins;
1017 | // create an empty array with numBins of items, later will store the number of values in that bin
1018 | let binFreqArr = new Array(numBins);
1019 |
1020 | that.sortData(xkey); // may not be necessary as we only looking for frequency
1021 |
1022 | let currentMinBound = xmin;
1023 | let currentMaxBound = xmin+binRange;
1024 | for (let j=0; j= currentMinBound) && (currentValue0) prevFreq = binFreqArr[q-1];
1057 |
1058 | let currentFreq = binFreqArr[q];
1059 |
1060 | if(qthis.data[i]._plotx-flakiness&&_xthis.data[i]._ploty-flakiness&&_ythis._xmax) this._xmax = this.data[i][xkey];
190 | if(this.data[i][ykey]this._ymax) this._ymax = this.data[i][ykey];
192 | }
193 |
194 | }
195 |
196 | //
197 | // sortData() - SORT AN ARRAY BASED ON A KEY
198 | //
199 | sortData(_key) {
200 | // sort by xkey
201 | this.data.sort(function(a, b) {
202 | return a[_key] - b[_key];
203 | });
204 |
205 |
206 | }
207 |
208 | //
209 | // LINE GRAPH
210 | //
211 | drawLineGraph() {
212 | let xkey = this.xkey;
213 | let ykey = this.ykey;
214 |
215 | let xmin = this._xmin;
216 | let xmax = this._xmax;
217 | let ymin = this._ymin;
218 | let ymax = this._ymax;
219 | let px = 0;
220 | let py = 0;
221 |
222 | push();
223 |
224 | fill(this.fillcolor);
225 | stroke(this.strokecolor);
226 | strokeWeight(this.strokeweight);
227 |
228 | this.sortData(xkey);
229 | for(let i in this.data)
230 | {
231 | this.data[i]._plotx = map(this.data[i][xkey], xmin, xmax, this.left, this.right);
232 | this.data[i]._ploty = map(this.data[i][ykey], ymin, ymax, this.bottom, this.top);
233 | let x = this.data[i]._plotx;
234 | let y = this.data[i]._ploty;
235 | if(i>0) line(px, py, x, y);
236 | px = x;
237 | py = y;
238 | }
239 | pop();
240 |
241 | }
242 |
243 | //
244 | // POINT GRAPH
245 | //
246 | drawPointGraph() {
247 | let xkey = this.xkey;
248 | let ykey = this.ykey;
249 |
250 | let xmin = this._xmin;
251 | let xmax = this._xmax;
252 | let ymin = this._ymin;
253 | let ymax = this._ymax;
254 |
255 | push();
256 |
257 | fill(this.fillcolor);
258 | stroke(this.strokecolor);
259 | strokeWeight(this.strokeweight);
260 |
261 | for(let i in this.data)
262 | {
263 | this.data[i]._plotx = map(this.data[i][xkey], xmin, xmax, this.left, this.right);
264 | this.data[i]._ploty = map(this.data[i][ykey], ymin, ymax, this.bottom, this.top);
265 | let x = this.data[i]._plotx;
266 | let y = this.data[i]._ploty;
267 |
268 | ellipse(x,y,5,5);
269 | }
270 |
271 | pop();
272 |
273 | }
274 |
275 | }; // end of p5.Plot()
276 |
277 |
278 | })); // end of craziness
279 |
280 | p5.Plot.prototype.drawAlex = function()
281 | {
282 |
283 | }
284 |
285 | /*
286 | p5.Plot.prototype.drawAlexHistogram = function(){
287 | // histogram is taking one contineous variable
288 | // mapping frequencies within each bin
289 | // here let's assume we only take xkey to plot our histogram
290 | let xkey = this.xkey;
291 | //let ykey = this.ykey;
292 |
293 | let xmin = this._xmin;
294 | let xmax = this._xmax;
295 | //let ymin = this._ymin;
296 | //let ymax = this._ymax;
297 |
298 | let numBins = this.bins;
299 | let binRange = (xmax-xmin)/numBins;
300 | let binArr = new Array(numBins);
301 |
302 | this.sortData(xkey); // may not be necessary as we only looking for frequency
303 |
304 | let currentMinBound = xmin;
305 | let currentMaxBound = xmin+binRange;
306 | for (let j=0; j= currentMinBound) && (currentValue maxFreq){
330 | maxFreq = currentFreq;
331 | }
332 | }
333 |
334 | console.log(minFreq);
335 | console.log(maxFreq);
336 |
337 | push();
338 |
339 | fill(this.fillcolor);
340 | stroke(this.strokecolor);
341 | strokeWeight(this.strokeweight);
342 |
343 | // start to draw rectangles!!!
344 | rectMode(CORNER); // x, y, w, h
345 | drawWidth = (this.right-this.left)/numBins; // width of each rect
346 | let currentX = this.left;
347 | for (let q=0; q0) vertex(x, y);
386 | }
387 | vertex(this.right, this.bottom);
388 |
389 | endShape(CLOSE);
390 |
391 | pop();
392 |
393 |
394 | }
395 | */
396 | /*
397 | p5.Plot.prototype.drawBoxPlot = function(){
398 | // draw box plot
399 | // graph minimum, first quartile, median, third quartile, and maximum
400 |
401 | // only makes sense when there's discrete y and continuous x or;
402 | // discrete x and continuous y
403 | // for example:
404 | // boxData = [{"x":13, "y":"a"}, {"x":16, "y":"a"}, {"x":57, "y":"a"}, {"x":34, "y":"a"}, {"x":26, "y":"a"}, {"x":67, "y":"a"}, {"x":12, "y":"a"},
405 | {"x":45, "y":"b"}, {"x":32, "y":"b"}, {"x":24, "y":"b"}, {"x":86, "y":"b"}, {"x":65, "y":"b"}, {"x":37, "y":"b"}, {"x":98, "y":"b"}];
406 |
407 |
408 | // here lets assume xkey is contineous and
409 | // ykey is discrete
410 | // draw horizontal graphs
411 | // the number of ykey represent number of boxes
412 | let xkey = this.xkey;
413 | let ykey = this.ykey;
414 |
415 | // if x is contineous, find min & max
416 | let xmin = this._xmin;
417 | let xmax = this._xmax;
418 |
419 | push();
420 |
421 | fill(this.fillcolor);
422 | stroke(this.strokecolor);
423 | strokeWeight(this.strokeweight);
424 |
425 | // if there's more than one set of continuous data
426 | // put every unique y value into the array
427 | let boxArr = [];
428 | let valueMin = xmin; //if given y value, this is useful
429 | let valueMax = xmax;
430 |
431 | // check in our data, how many unique y & push them into new array
432 | // if no ykey is given, y would just be default 1, apparently
433 | for(let i in this.data){
434 | if (boxArr.includes(this.data[i][ykey])){
435 | }
436 | else{
437 | boxArr.push(this.data[i][ykey]);
438 | }
439 | }
440 |
441 | let numBox = boxArr.length;
442 | let boxMargin = ((this.bottom-this.top)/numBox)/10;
443 | let boxY = this.top+boxMargin;
444 | let boxHeight = (this.bottom-this.top)/numBox - boxMargin*2;
445 |
446 | // for every box array value, draw a box
447 | for (let j=0; jvalueMax){
457 | valueMax = this.data[k][xkey]
458 | }
459 | }
460 |
461 | let xQuartileBoundsArr = quartileBounds(valueArr);
462 | // map minimum, first quartile, median, third quartile, and maximum into the graph
463 | // two graphs should have a common scale instead of their own scale
464 | let boxMin = map(xQuartileBoundsArr[0], valueMin, valueMax, this.left, this.right);
465 | let boxQ1 = map(xQuartileBoundsArr[1], valueMin, valueMax, this.left, this.right);
466 | let boxMedian = map(xQuartileBoundsArr[2], valueMin, valueMax, this.left, this.right);
467 | let boxQ3 = map(xQuartileBoundsArr[3], valueMin, valueMax, this.left, this.right);
468 | let boxMax = map(xQuartileBoundsArr[4], valueMin, valueMax, this.left, this.right);
469 |
470 | console.log(boxMin+' '+boxQ1+' '+boxMedian+' '+boxQ3+' '+ boxMax);
471 |
472 | // graph multiple horizontal box plots after dealing with data
473 |
474 | // the height of box, keep it constant
475 | //let boxHeight = this.bottom-this.top;
476 |
477 | drawOneBox(boxMin, boxQ1, boxMedian, boxQ3, boxMax, boxY, boxHeight);
478 |
479 | //draw next box, the Y pos will increase!
480 | boxY += boxMargin + boxHeight;
481 | }
482 | pop();
483 | }
484 |
485 | // find the median
486 | // if array is odd number, median is middle number
487 | // if array is even number, median is middle two numbers added then divide by two
488 | function getMedian(sampleArr){
489 | sampleArr.sort(function(a, b){return a - b});
490 | // even
491 | if (sampleArr.length%2 === 0){
492 | let numA = sampleArr[sampleArr.length/2 - 1];
493 | let numB = sampleArr[sampleArr.length/2];
494 | return (numA + numB)/2;
495 | }
496 | // odd
497 | else{
498 | return sampleArr[(sampleArr.length - 1)/2];
499 | }
500 | }
501 |
502 | // find medians and quartiles
503 | function quartileBounds(sampleArr){
504 | // must sort array first
505 | sampleArr.sort(function(a, b){return a - b});
506 | let _firstHalf;
507 | let _secondHalf;
508 | // even
509 | if (sampleArr.length%2 === 0){
510 | _firstHalf = sampleArr.slice(0, sampleArr.length/2);
511 | _secondHalf = sampleArr.slice(sampleArr.length/2, sampleArr.length);
512 | }
513 | // odd
514 | else {
515 | _firstHalf = sampleArr.slice(0, (sampleArr.length-1)/2);
516 | _secondHalf = sampleArr.slice(((sampleArr.length-1)/2)+1, sampleArr.length);
517 | }
518 | let _0percent = min(sampleArr);
519 |
520 | // find the medians for each split
521 | let _25percent = getMedian(_firstHalf);
522 | let _75percent = getMedian(_secondHalf);
523 |
524 | let _50percent = getMedian(sampleArr);
525 | let _100percent = max(sampleArr);
526 |
527 | return [ _0percent, _25percent, _50percent, _75percent, _100percent];
528 | }
529 |
530 | function drawOneBox(boxMin, boxQ1, boxMed, boxQ3, boxMax, boxY, boxHeight){
531 | line(boxMin, boxY+boxHeight/4, boxMin, boxY+boxHeight/4+boxHeight/2); // minimum
532 |
533 | line(boxQ1, boxY, boxQ1, boxY+boxHeight); // Q1
534 |
535 | line(boxMed, boxY, boxMed, boxY+boxHeight); // median
536 |
537 | line(boxQ3, boxY, boxQ3, boxY+boxHeight); // Q3
538 |
539 | line(boxMax, boxY+boxHeight/4, boxMax, boxY+boxHeight/4+boxHeight/2); //maximum
540 |
541 | // connect
542 | line(boxQ1, boxY, boxQ3, boxY); // top of box
543 | line(boxQ1, boxY+boxHeight, boxQ3, boxY+boxHeight); // bot of box
544 | line(boxMin, boxY+boxHeight/2, boxQ1, boxY+boxHeight/2);
545 | line(boxQ3, boxY+boxHeight/2, boxMax, boxY+boxHeight/2);
546 | }
547 | */
548 | /*
549 | p5.Plot.prototype.drawDensityGraph = function(){
550 | // density graph is taking one contineous variable
551 | // here we assume a bin is given, !!!!!!!!!!!!but possibly no bin and discrete data is given!!!!!!!!!
552 | // mapping frequencies within each bin
553 | // find the percentage of the frequency
554 |
555 | // here let's assume we only take xkey
556 | let xkey = this.xkey;
557 | //let ykey = this.ykey;
558 |
559 | let xmin = this._xmin;
560 | let xmax = this._xmax;
561 | //let ymin = this._ymin;
562 | //let ymax = this._ymax;
563 |
564 | let numBins = this.bins;
565 | let binRange = (xmax-xmin)/numBins;
566 | // create an empty array with numBins of items, later will store the number of values in that bin
567 | let binFreqArr = new Array(numBins);
568 |
569 | this.sortData(xkey); // may not be necessary as we only looking for frequency
570 |
571 | let currentMinBound = xmin;
572 | let currentMaxBound = xmin+binRange;
573 | for (let j=0; j= currentMinBound) && (currentValue0) prevFreq = binFreqArr[q-1];
607 |
608 | let currentFreq = binFreqArr[q];
609 |
610 | if(qthis._xmax) this._xmax = this.data[i][xkey];
794 | if(this.data[i][ykey]this._ymax) this._ymax = this.data[i][ykey];
796 | }
797 | }
798 | }
799 |
800 |
801 | ///////////// STUFF SALLY WORKED ON /////////////////////////
802 |
803 | p5.Plot.prototype.drawBarGraph = function()
804 | {
805 | //let xkey = this.xkey;
806 | //let ykey = this.ykey;
807 | let key;
808 | let max;
809 | let keyArr;
810 | let keyObj;
811 | let spacing
812 |
813 | this._ymin = 0;
814 | this._xmin = 0;
815 |
816 | if (this.xkey != 0){
817 | keyArr = this.barSort(this.xkey);
818 | key = this.xkey;
819 | keyObj = this.barParse(key);
820 | spacing = (this.right - this.left)/keyArr.length;
821 | }
822 | else if (this.ykey != 1){
823 | keyArr = this.barSort(this.ykey);
824 | key = this.ykey;
825 | keyObj = this.barParse(key);
826 | spacing = (this.bottom - this.top)/keyArr.length
827 | }
828 |
829 | fill(this.fillcolor);
830 | stroke(this.strokecolor);
831 | strokeWeight(this.strokeweight);
832 | max = keyObj[0].quantity;
833 |
834 | for(let i in keyObj){
835 | if(keyObj[i].quantity > max){max = keyObj[i].quantity;}
836 | }
837 |
838 | if (key == this.xkey){
839 | this._xmax = keyArr.length;
840 | this._ymax = max;
841 | }
842 | else if (key == this.ykey){
843 | this._xmax = max;
844 | this._ymax = keyArr.length;
845 | }
846 |
847 |
848 | push();
849 | let x;
850 | let y;
851 | let w;
852 | let h;
853 |
854 | if (key == this.xkey){
855 | x = this.left;
856 | y= 0;
857 | w= this.left;
858 | h= 0;
859 | }
860 | else if (key == this.ykey){
861 | x = this.left;
862 | y = this.top;
863 | w = 0;
864 | h = this.top;
865 | }
866 |
867 | rectMode(CORNERS);
868 |
869 | for(let k=0; k < keyObj.length; k++)
870 | {
871 | if (key == this.xkey){
872 | y = map(keyObj[k].quantity, 0, this._ymax, this.bottom, this.top);
873 | w += spacing;
874 | h = this.bottom;
875 | rect(x, y, w, h)
876 | x += spacing;
877 | }
878 | else if (key == this.ykey){
879 | h += spacing;
880 | w = map(keyObj[k].quantity, 0, max, this.left, this.right)
881 | rect(x, y, w, h)
882 | y+= spacing;
883 | }
884 | }
885 |
886 | pop();
887 | }
888 |
889 | p5.Plot.prototype.barSort = function(_key){
890 | keyArr = [this.data[0][_key]];
891 | this.data[0][_key] = 0;
892 |
893 | for(let i=1;i qmax){qmax = keyObj[i].quantity;}
945 | }
946 |
947 | console.log(keyObj);
948 |
949 | push();
950 |
951 | let xone = (this.right - this.left) / xDots;
952 | let xhalf = xone / 2;
953 | let yone = (this.top - this.bottom)/yDots
954 | let yhalf = yone / 2
955 |
956 |
957 | let x = this.left + xhalf;
958 | let y = this.bottom + yhalf;
959 | let w;
960 |
961 | if (yone <= xone){w = yone;}
962 | else{w = xone;}
963 |
964 | ellipseMode(CENTER);
965 |
966 |
967 | for(let k=0; k < keyObj.length; k++) {
968 | let dotNum = keyObj[k].quantity / yDots;
969 | for(let j = 0; j < dotNum; j++){
970 | ellipse(x, y, w);
971 | y += yone;
972 | }
973 | x += xone;
974 | y = this.bottom + yhalf;
975 |
976 | }
977 | pop();
978 |
979 | }
980 |
981 |
982 | p5.Plot.prototype.drawHistogram = function(){
983 |
984 | let range;
985 | let min;
986 | let max;
987 | let key;
988 | let bars;
989 |
990 | if (this.xkey != 0){
991 | range = this._xmax - this._xmin;
992 | max = this._xmax;
993 | min = this._xmin;
994 | key = this.xkey;
995 | bars = this.cols;
996 | }
997 | else if (this.ykey != 1){
998 | range = this._ymax - this._ymin;
999 | max = this._ymax;
1000 | min = this._ymin;
1001 | key = this.ykey;
1002 | bars = this.rows;
1003 | }
1004 | while (range % bars != 0){
1005 | range += 1;
1006 | }
1007 | let barRange = range / bars;
1008 | let keyArr = this.findKeys(barRange, min,max);
1009 | let keyObj = this.histParse(keyArr, key, barRange);
1010 |
1011 | fill(this.fillcolor);
1012 | stroke(this.strokecolor);
1013 | strokeWeight(this.strokeweight);
1014 |
1015 | let qmax = keyObj[0].quantity;
1016 |
1017 | for(let i in keyObj){
1018 | if(keyObj[i].quantity > qmax){qmax = keyObj[i].quantity;}
1019 | }
1020 |
1021 | console.log(keyObj);
1022 |
1023 | push();
1024 |
1025 | let x;
1026 | let y;
1027 | let w;
1028 | let h;
1029 | let spacing
1030 |
1031 | if (key == this.xkey){
1032 | x = this.left;
1033 | y= 0;
1034 | w= this.left;
1035 | h= 0;
1036 | spacing = (this.right - this.left)/(this.cols);
1037 |
1038 | }
1039 | else if (key == this.ykey){
1040 | x = this.left;
1041 | y = this.top;
1042 | w = 0;
1043 | h = this.top;
1044 | spacing = (this.top - this.bottom)/this.rows;
1045 | }
1046 |
1047 | rectMode(CORNERS);
1048 |
1049 | for(let k=0; k < keyObj.length; k++)
1050 | {
1051 | if (key == this.xkey){
1052 | y = map(keyObj[k].quantity, 0, qmax, this.bottom, this.top);
1053 | w += spacing;
1054 | h = this.bottom;
1055 | rect(x, y, w, h)
1056 | x += spacing;
1057 |
1058 | }
1059 | else if (key == this.ykey){
1060 | h -= spacing;
1061 | w = map(keyObj[k].quantity, 0, qmax, this.left, this.right)
1062 | rect(x, y, w, h)
1063 | y-= spacing;
1064 | }
1065 | }
1066 |
1067 |
1068 | pop();
1069 |
1070 | }
1071 |
1072 | p5.Plot.prototype.findKeys = function(barRange, min, max){
1073 | let keyArr = [];
1074 | let mult = 0;
1075 | while ((mult * barRange) < min){
1076 | mult += 1;
1077 | }
1078 | mult -=1;
1079 | for (i = 0; i < this.cols; i++){
1080 | keyArr.push(mult);
1081 | mult += 1;
1082 | }
1083 | return keyArr;
1084 | }
1085 |
1086 | p5.Plot.prototype.histParse = function(keyArr, key, barRange){
1087 | keyObj = [{"key": (keyArr[0]* barRange) + "-" + ((keyArr[0] + 1) * barRange), "quantity": 0}];
1088 |
1089 | for(let j=1; j= keyArr[keyArr.length - 1] * barRange){
1097 | keyObj[keyArr.length - 1].quantity += 1;
1098 | }
1099 | else if (num >= keyArr[i] * barRange && num < keyArr[i + 1] * barRange){
1100 | keyObj[i].quantity += 1
1101 | }
1102 | }
1103 | }
1104 | return keyObj;
1105 | }
1106 |
--------------------------------------------------------------------------------
/lib/p5.simpleplot.js:
--------------------------------------------------------------------------------
1 | // p5.Plot
2 | // "grammar of graphics" influenced data viz for p5.js
3 | // creative coding summer vibes team, NYU IDM, 2018
4 | //
5 |
6 |
7 | // the plan should be
8 | // the constructor lets you set up whatever parameters you want
9 | // but won't render anything
10 | // plot() renders to a p5.createGraphics
11 | // redraw() plunks down the p5.graphics context already plot()'ed
12 | // hover() draws the fucker on top of the graphics context
13 |
14 | // the usual craziness:
15 | (function (root, factory) {
16 | if (typeof define === 'function' && define.amd)
17 | define('p5.func', ['p5'], function (p5) { (factory(p5));});
18 | else if (typeof exports === 'object')
19 | factory(require('../p5'));
20 | else
21 | factory(root['p5']);
22 | }(this, function (p5) {
23 |
24 | //
25 | // start real stuff
26 | //
27 |
28 | // new style:
29 | p5.Plot = class {
30 |
31 | // this runs when you instantiate:
32 | // (also contains property defaults)
33 | constructor (_args) {
34 |
35 | //
36 | // defaults:
37 | //
38 | this.type = 'line'; // type of plot
39 | this.stat = 'bin'; // statistical transformation for 1-var plots
40 | this.bins = 30; // number of slices in binning plots
41 | this.left = 0;
42 | this.top = 0;
43 | this.pointdiameter = 5;
44 | this.right = width;
45 | this.bottom = height;
46 | this._data = {};
47 | //this.xkey = ""; // key value for x axis
48 | //this.ykey = ""; // key value for y axis
49 | this._xkey = [];
50 | this._ykey = [];
51 | this._needsparse = true;
52 | this._needssort = true;
53 |
54 | this.typelist = {};
55 |
56 | // function definitions
57 | this.typelist.line = { // continuous function x y
58 | xtype: 'continuous',
59 | ytype: 'continuous',
60 | function: this.drawLineGraph
61 | };
62 |
63 | this.typelist.point = { // continuous x, continuous y
64 | xtype: 'continuous',
65 | ytype: 'continuous',
66 | function: this.drawPointGraph
67 | };
68 |
69 | //
70 | // end defaults
71 | //
72 |
73 | // internals:
74 | this._xmin; // internal
75 | this._xmax; // internal
76 | this._ymin; // internal
77 | this._ymax; // internal
78 |
79 |
80 | // integrate arguments:
81 | // this is an awesome ES6 hack where the Object.assign()
82 | // method lets you splice shit from one Object literal into
83 | // another Object, just replacing whatever's there.
84 | for(let i in arguments)
85 | {
86 | Object.assign(this, arguments[i]);
87 | }
88 |
89 | this.plotData = []; // create a new dataset to workwith instead of changing the original
90 | console.log('p5 plot!');
91 |
92 | }; // end of constructor
93 |
94 | // setters:
95 | set xkey (xkey) {
96 | this._xkey = Array.isArray(xkey) ? xkey : [xkey];
97 | }
98 | get xkey() {
99 | return this._xkey;
100 | }
101 | set ykey (ykey) {
102 | this._ykey = Array.isArray(ykey) ? ykey : [ykey];
103 | }
104 | get ykey() {
105 | return this._ykey;
106 | }
107 | set data (data) {
108 | this._data = data;
109 | this._needsparse = true;
110 | this._needssort = true;
111 | }
112 | get data() {
113 | return this._data;
114 | }
115 |
116 |
117 |
118 | // MAIN PLOTTER FUNCTION
119 | //
120 | plot (_args) {
121 |
122 | // integrate arguments (see above):
123 | for(let i in arguments)
124 | {
125 | Object.assign(this, arguments[i]);
126 | }
127 | // console.log(this.dataUnchanged(this.prevdata, this._data));
128 | // how do we only run this once unless the 'data' parameter changes:
129 | // if (!this.dataUnchanged(this.prevdata, this._data)){
130 | // this.parseData(); // figure out min and max scalings, etc.
131 | // }
132 |
133 | if(this._needsparse) this.parseData();
134 |
135 | // which graph style?
136 | // draw the graphs
137 | if(Array.isArray(this.type)) {
138 | for(let i in this.type)
139 | {
140 | this.typelist[this.type[i]].function(this);
141 | }
142 | }
143 | else {
144 | this.typelist[this.type].function(this);
145 | }
146 |
147 | }; // END OF MAIN PLOTTER FUNCTION
148 |
149 | //
150 | // parseData() - MAKE SENSE OF THE DATASET
151 | //
152 | parseData() {
153 | console.log("PARSING!!! " + millis());
154 | //console.log(this.dataUnchanged());
155 | // STEP ONE:
156 | // what happens if the data array is not made up of object literals
157 |
158 | // simple array test:
159 | if(Array.isArray(this._data) && typeof(this._data[0])==="number")
160 | {
161 | var _newdata = this.tokenize(this._data); // fix
162 | this._data = _newdata; // swap
163 | }
164 |
165 | // STEP TWO:
166 | // fix if we have no xkey / ykey defined
167 | if(this._xkey.length==0){
168 | this._xkey = [Object.keys(this._data[0])[0]];
169 | }
170 | if(this._ykey.length==0){
171 | this._ykey = [Object.keys(this._data[0])[1]];
172 | }
173 |
174 | // STEP THREE:
175 | // make sure the keys are the right type
176 | // console.log(this.typelist[this.type].xtype + " " + this.typelist[this.type].ytype);
177 |
178 | this._xmin = this._data[0][this._xkey[0]];
179 | this._xmax = this._data[0][this._xkey[0]];
180 | this._ymin = this._data[0][this._ykey[0]];
181 | this._ymax = this._data[0][this._ykey[0]];
182 |
183 | for(let i=0;ithis._xmax) this._xmax = this._data[i][this._xkey[j]];
189 | currentData[this._xkey[j]] = this._data[i][this._xkey[j]];
190 | }
191 |
192 | // ykey
193 | for (let k=0; kthis._ymax) this._ymax = this._data[i][this._ykey[k]];
196 | currentData[this._ykey[k]] = this._data[i][this._ykey[k]];
197 | }
198 |
199 | // data we actually use
200 | this.plotData.push(currentData);
201 | }
202 |
203 | this._needsparse = false;
204 |
205 | } // end of parseData
206 |
207 | //
208 | // SORT AN ARRAY BASED ON A KEY
209 | //
210 | sortData(_key) {
211 | console.log("SORTING!!! " + millis());
212 | // sort by xkey
213 | this._data.sort(function(a, b) {
214 | return a[_key] - b[_key];
215 | });
216 |
217 | this.plotData.sort(function(a, b) {
218 | return a[_key] - b[_key];
219 | });
220 |
221 | this._needssort = false;
222 | }
223 |
224 | //
225 | // TOKENIZE - utility to JSONify a simple array
226 | //
227 | tokenize(_arr) {
228 | var a = [];
229 | for(var i in _arr)
230 | {
231 | var j = {};
232 | j.index = i;
233 | j.value = _arr[i];
234 | a.push(j);
235 | }
236 | return(a);
237 | }
238 |
239 | //
240 | // LINE GRAPH
241 | //
242 | drawLineGraph(that) {
243 |
244 | push();
245 | // need to figure out a way to do this for all graphs
246 | // faceting: multiple xkeys
247 | // iterate through all x keys
248 |
249 | // what happens when multiple xkeys and ykeys?
250 | for (let i=0; i';
204 | this.svgfoot = '';
205 |
206 | // which graph style?
207 | // DRAW THE GRAPHS!!!
208 | if(Array.isArray(this.type)) {
209 | for(let i in this.type)
210 | {
211 | this.typelist[this.type[i]].function(this);
212 | }
213 | }
214 | else {
215 | this.typelist[this.type].function(this);
216 | }
217 |
218 | this.drawBG(this);
219 |
220 | // concatenate HTML and make it base64
221 | svg64 = btoa(this.svghead+this.bgsvghtml+this.svghtml+this.svgfoot);
222 |
223 | // prepend a base64 "header"
224 | plotSVGURL = b64Start + svg64;
225 |
226 | // load to p5.Image
227 | this.plotImg = loadImage(plotSVGURL);
228 |
229 |
230 | }; // END OF MAIN PLOTTER FUNCTION
231 |
232 | // draw function display
233 | draw(_x=this.left, _y=this.top, _w=this.width, _h=this.height){
234 | image(this.plotImg, _x, _y, _w, _h);
235 | }
236 |
237 | //
238 | // parseData() - MAKE SENSE OF THE DATASET
239 | //
240 | parseData() {
241 | // console.log("PARSING!!! " + millis());
242 | // console.log(this.dataUnchanged());
243 | // STEP ONE:
244 | // what happens if the data array is not made up of object literals
245 |
246 | // simple array test:
247 | if(Array.isArray(this._data) && typeof(this._data[0])==="number")
248 | {
249 | var _newdata = this.tokenize(this._data); // fix
250 | this._data = _newdata; // swap
251 | }
252 | else if(Array.isArray(this._data) && typeof(this._data[0])==="string")
253 | {
254 | var _newdata = this.strtokenize(this._data); // fix
255 | this._data = _newdata; // swap
256 | }
257 |
258 | // STEP TWO:
259 | // fix if we have no xkey / ykey defined
260 | if(this._xkey.length==0){
261 | this._xkey = [Object.keys(this._data[0])[0]];
262 | }
263 | if(this._ykey.length==0){
264 | this._ykey = [Object.keys(this._data[0])[1]];
265 | }
266 |
267 | // STEP THREE:
268 | // make sure the keys are the right type
269 | // console.log(this.typelist[this.type].xtype + " " + this.typelist[this.type].ytype);
270 |
271 | this._xmin = this._data[0][this._xkey[0]];
272 | this._xmax = this._data[0][this._xkey[0]];
273 | this._ymin = this._data[0][this._ykey[0]];
274 | this._ymax = this._data[0][this._ykey[0]];
275 |
276 | for(let i=0;ithis._xmax) this._xmax = this._data[i][this._xkey[j]];
282 | currentData[this._xkey[j]] = this._data[i][this._xkey[j]];
283 | }
284 |
285 | // ykey
286 | for (let k=0; kthis._ymax) this._ymax = this._data[i][this._ykey[k]];
289 | currentData[this._ykey[k]] = this._data[i][this._ykey[k]];
290 | }
291 |
292 | currentData.constant = "1";
293 |
294 | // data we actually use
295 | this.plotData.push(currentData);
296 | }
297 |
298 | this._needsparse = false;
299 |
300 | } // end of parseData
301 |
302 | //
303 | // SORT AN ARRAY BASED ON A KEY
304 | //
305 | sortData(_key) {
306 | // console.log("SORTING!!! " + millis());
307 | // sort by xkey
308 | this._data.sort(function(a, b) {
309 | return a[_key] - b[_key];
310 | });
311 |
312 | this.plotData.sort(function(a, b) {
313 | return a[_key] - b[_key];
314 | });
315 |
316 | this._needssort = false;
317 | }
318 |
319 | //
320 | // TOKENIZE - utility to JSONify a simple array
321 | //
322 | tokenize(_arr) {
323 | console.log("tokenizing!");
324 | var a = [];
325 | for(var i in _arr)
326 | {
327 | var j = {};
328 | j.index = i;
329 | j.value = _arr[i];
330 | a.push(j);
331 | }
332 | this._istokenized = true;
333 | return(a);
334 | }
335 |
336 | //
337 | // STRTOKENIZE - utility to JSONify a simple string array
338 | //
339 | strtokenize(_arr) {
340 | var a = [];
341 | for(var i in _arr)
342 | {
343 | var j = {};
344 | j.key = _arr[i];
345 | a.push(j);
346 | }
347 | this._istokenized = true;
348 | return(a);
349 | }
350 |
351 | //
352 | // LINE GRAPH
353 | //
354 | drawLineGraph(that) {
355 |
356 | push();
357 | // need to figure out a way to do this for all graphs
358 | // faceting: multiple xkeys
359 | // iterate through all x keys
360 |
361 | // what happens when multiple xkeys and ykeys?
362 | for (let i=0; i';
382 | that.gridcols = 10;
383 |
384 | }
385 |
386 | //
387 | // POINT GRAPH
388 | //
389 | drawPointGraph(that) {
390 | push();
391 |
392 | // iterate through all xkeys
393 | for (let i=0; i';
403 |
404 | }
405 | }
406 | pop();
407 | that.gridcols = 10;
408 | }
409 |
410 | drawBarGraph1(that){
411 | // discrete x, count occurances of each unique x
412 | let uniqueXArr = [];
413 | let countArr = [];
414 |
415 | for(let i=0;i';
438 |
439 | /* how to draw rect in svg
440 |
442 | */
443 | barX += barW;
444 | }
445 |
446 | that.gridcols = uniqueXArr.length;
447 | that.gridcollabs = uniqueXArr;
448 | console.log(that.svghtml);
449 | }
450 |
451 | drawBarGraph2(that){
452 | // discrete x, continuous y, add all y for each unique x
453 | let uniqueXArr = [];
454 | let totalYArr = [];
455 |
456 | for(let i=0;i';
483 |
484 | /* how to draw rect in svg
485 |
487 | */
488 | barX += barW;
489 | }
490 |
491 | that.gridcols = uniqueXArr.length;
492 | that.gridcollabs = uniqueXArr;
493 | console.log(that.svghtml);
494 | }
495 |
496 | drawBoxPlot(that){
497 | // data: discrete x, continuous y, where every unique x is one box plot, and we use the set of corresponding y numbers
498 | // OR a set of numbers, where we CANNOT tokenize
499 | // find minimum, first quartile, median, third quartile, and maximum for each box plot
500 | let oxkey = that._xkey;
501 | that._xkey = "constant";
502 |
503 | console.log(that.plotData);
504 | let uniqueXArr = [];
505 | // do your thing
506 |
507 |
508 | // restore xkey
509 | that._xkey = oxkey;
510 | }
511 |
512 | //
513 | // Utility Functions
514 | //
515 |
516 | // find the median
517 | // if array is odd number, median is middle number
518 | // if array is even number, median is middle two numbers added then divide by two
519 | // takes in a number array, return the median number
520 | getMedian(sampleArr){
521 | sampleArr.sort(function(a, b){return a - b}); // sort from low to high
522 | // even
523 | if (sampleArr.length%2 === 0){
524 | let numA = sampleArr[sampleArr.length/2 - 1];
525 | let numB = sampleArr[sampleArr.length/2];
526 | return (numA + numB)/2;
527 | }
528 | // odd
529 | else{
530 | return sampleArr[(sampleArr.length - 1)/2];
531 | }
532 | }
533 |
534 | // find medians and quartiles
535 | // takes in a number array, gives an array of values: minimum, first quartile, median, third quartile, and maximum
536 | quartileBounds(sampleArr){
537 | sampleArr.sort(function(a, b){return a - b}); // sort from low to high
538 | let _firstHalf;
539 | let _secondHalf;
540 | // even
541 | if (sampleArr.length%2 === 0){
542 | _firstHalf = sampleArr.slice(0, sampleArr.length/2);
543 | _secondHalf = sampleArr.slice(sampleArr.length/2, sampleArr.length);
544 | }
545 | // odd
546 | else {
547 | _firstHalf = sampleArr.slice(0, (sampleArr.length-1)/2);
548 | _secondHalf = sampleArr.slice(((sampleArr.length-1)/2)+1, sampleArr.length);
549 | }
550 | let _0percent = min(sampleArr);
551 |
552 | // find the medians for each split
553 | let _25percent = this.getMedian(_firstHalf);
554 | let _75percent = this.getMedian(_secondHalf);
555 |
556 | let _50percent = this.getMedian(sampleArr);
557 | let _100percent = max(sampleArr);
558 |
559 | return [ _0percent, _25percent, _50percent, _75percent, _100percent];
560 | }
561 |
562 | // draw grid background
563 | drawBG(that)
564 | {
565 | // lines
566 | let x0 = that.padding*that.aa;
567 | let x1 = (that.width-that.padding)*that.aa;
568 | let y0 = that.padding*that.aa;
569 | let y1 = (that.height-that.padding)*that.aa;
570 | let i, xi, yi;
571 |
572 | // bounding box
573 | this.bgsvghtml += '';
574 | this.bgsvghtml += '';
575 | this.bgsvghtml += '';
576 | this.bgsvghtml += '';
577 |
578 | for(i = 1;i';
584 | if(that.gridcollabs.length>0)
585 | {
586 | this.bgsvghtml += ''+that.gridcollabs[i-1]+'';
587 | }
588 | }
589 |
590 | for(i = 1;i';
596 | }
597 |
598 | console.log(this.bgsvghtml);
599 | }
600 |
601 | colorfucker(_c)
602 | {
603 | var rc;
604 | var cm0 = colorMode()._colorMaxes[colorMode()._colorMode][0]; // r/h
605 | var cm1 = colorMode()._colorMaxes[colorMode()._colorMode][1]; // g/s
606 | var cm2 = colorMode()._colorMaxes[colorMode()._colorMode][2]; // b/b/l
607 | var cm3 = colorMode()._colorMaxes[colorMode()._colorMode][3]; // a
608 |
609 | // in CSS, the maxes are:
610 | // for rgba: 255, 255, 255, 1
611 | // for hsla: 360, 100%, 100%, 1
612 |
613 | if(Array.isArray(_c)){
614 | if(_c.length==1) rc = "rgb("+_c[0]+", " + _c[0] + ", " + _c[0] + ")";
615 | if(_c.length==2) rc = "rgba("+_c[0]+", " + _c[0] + ", " + _c[0] + ", " + _c[1]/255 + ")";
616 | if(_c.length==3&&colorMode()._colorMode=="rgb") rc = "rgb("+_c[0]/cm0*255+", " + _c[1]/cm1*255 + ", " + _c[2]/cm2*255 + ")";
617 | if(_c.length==4&&colorMode()._colorMode=="rgb") rc = "rgba("+_c[0]/cm0*255+", " + _c[1]/cm1*255 + ", " + _c[2]/cm2*255 + ", " + _c[3]/cm3 + ")";
618 | if(_c.length==3&&(colorMode()._colorMode=="hsb"||colorMode()._colorMode=="hsl")) rc = "hsl("+_c[0]/cm0*360+", " + _c[1]/cm1*100 + "%, " + _c[2]/cm2*100 + "%)";
619 | if(_c.length==4&&(colorMode()._colorMode=="hsb"||colorMode()._colorMode=="hsl")) rc = "hsla("+_c[0]/cm0*360+", " + _c[1]/cm1*100 + "%, " + _c[2]/cm2*100 + "%, " + _c[3]/cm3 + ")";
620 | }
621 | else if(Number.isInteger(_c)) {
622 | rc = "rgb("+_c+", " + _c + ", " + _c + ")";
623 | }
624 | else {
625 | rc = _c;
626 | }
627 | return(rc);
628 | }
629 |
630 | }; // end of p5.Plot()
631 | })); // end of craziness
632 |
--------------------------------------------------------------------------------
/rtests/testing/.RData:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IDMNYU/p5.js-plot/6b4c0ab6e1e1a8bf4a302d175067026ef127113a/rtests/testing/.RData
--------------------------------------------------------------------------------
/rtests/testing/.Rhistory:
--------------------------------------------------------------------------------
1 | library(ggplot2)
2 | library(usmap)
3 | library(gtable)
4 | library(grid)
5 | library(gridExtra)
6 | library(reshape2)
7 | install.packages(gridExtra)
8 | install.packages('gridExtra')
9 | library(ggplot2)
10 | library(usmap)
11 | library(gtable)
12 | library(grid)
13 | library(gridExtra)
14 | library(reshape2)
15 | library(reshape2)
16 | library(tidyverse)
17 | b = ggplot(mpg, aes(fl))
18 | b + geom_bar()
19 | mpg
20 | b <= ggplot(mpg, aes(fl))
21 | b + geom_bar()
22 | library(ggplot2)
23 | library(usmap)
24 | library(gtable)
25 | library(grid)
26 | library(gridExtra)
27 | library(reshape2)
28 | library(tidyverse)
29 | b <= ggplot(mpg, aes(fl))
30 | b <- ggplot(mpg, aes(fl))
31 | b + geom_bar()
32 | g <- ggplot(mpg, aes(class, hwy))
33 | g+geom_bar(state="identity")
34 | g <- ggplot(mpg, aes(class, hwy))
35 | g+geom_bar(stat="identity")
36 | g <- ggplot(mpg, aes(fl, hwy))
37 | g+geom_bar(stat="identity")
38 | b <- ggplot(mpg, aes(fl))
39 | b + geom_bar()
40 | g <- ggplot(mpg, aes(fl, hwy))
41 | g+geom_bar(stat="identity")
42 | g <- ggplot(mpg, aes(x=fl, y=hwy))
43 | g+geom_bar(stat="identity")
44 | b <- ggplot(mpg, aes(x=fl))
45 | b + geom_bar()
46 | g <- ggplot(mpg, aes(x=fl, y=hwy))
47 | g+geom_bar(stat="identity")
48 | mpg
49 | g <- ggplot(mpg, aes(x=fl, y=hwy))
50 | g+geom_bar()
51 | g <- ggplot(mpg, aes(x=fl))
52 | g+geom_bar()
53 | b <- ggplot(mpg, aes(x=fl))
54 | b + geom_bar()
55 | # count up how many of each kind of 'fl':
56 | b <- ggplot(mpg, aes(x=fl))
57 | b + geom_bar()
58 | # count up how much 'hwy' is in each 'fl':
59 | g <- ggplot(mpg, aes(x=hwy, y=fl))
60 | g+geom_bar(stat="identity")
61 | # count up how much 'hwy' is in each 'fl':
62 | g <- ggplot(mpg, aes(x=hwy, y=fl))
63 | g+geom_bar()
64 | # count up how much 'hwy' is in each 'fl':
65 | g <- ggplot(mpg, aes(x=fl, y=hwy))
66 | g+geom_bar(stat="identity")
67 | library(ggplot2)
68 | library(usmap)
69 | library(gtable)
70 | library(grid)
71 | library(gridExtra)
72 | library(reshape2)
73 | library(tidyverse)
74 | mpg
75 | # count up how many of each kind of 'fl':
76 | b <- ggplot(mpg, aes(x=fl))
77 | b + geom_bar()
78 | # count up how much 'hwy' is in each 'fl':
79 | g <- ggplot(mpg, aes(x=fl, y=hwy))
80 | g+geom_bar(stat="identity")
81 | library(ggplot2)
82 | library(usmap)
83 | library(gtable)
84 | library(grid)
85 | library(gridExtra)
86 | library(reshape2)
87 | library(tidyverse)
88 | mpg
89 | # count up how many of each kind of 'fl':
90 | b <- ggplot(mpg, aes(x=fl))
91 | b + geom_bar()
92 | # count up how much 'hwy' is in each 'fl':
93 | g <- ggplot(mpg, aes(x=fl, y=hwy))
94 | g+geom_bar(stat="identity")
95 | # count up how many of each kind of 'fl':
96 | b <- ggplot(mpg, aes(x=fl))
97 | b + geom_bar()
98 | # count up how much 'hwy' is in each 'fl':
99 | g <- ggplot(mpg, aes(x=fl, y=hwy))
100 | g+geom_bar(stat="identity")
101 | # count up how many of each kind of 'fl':
102 | b <- ggplot(mpg, aes(x=fl))
103 | b + geom_bar()
104 | f <- ggplot(mpg, aes(cty, hwy))
105 | f+geom_point()
106 | f+geom_smooth(model=lm)
107 | f+geom_point()
108 | f+geom_smooth(model=lm)
109 | f+geom_point()+geom_smooth(model=lm)
110 | f
111 | f
112 | mpg
113 | f
114 | f<-manufacturer
115 | fdeaths
116 | library(ggplot2)
117 | library(usmap)
118 | library(gtable)
119 | library(grid)
120 | library(gridExtra)
121 | library(reshape2)
122 | library(tidyverse)
123 | f <- ggplot(mpg, aes(cty, hwy))
124 | a <- ggplot(mpg, aes(hwy))
125 | ,bwei