Skip to content

Instantly share code, notes, and snippets.

@blmoore
Last active August 29, 2015 14:15
Show Gist options
  • Save blmoore/54a871e0df5838dfaf19 to your computer and use it in GitHub Desktop.
Save blmoore/54a871e0df5838dfaf19 to your computer and use it in GitHub Desktop.
<!doctype HTML>
<meta charset = 'utf-8'>
<html>
<head>
<script src='//d3js.org/d3.v3.min.js' type='text/javascript'></script>
<script src='//dimplejs.org/dist/dimple.v2.1.0.min.js' type='text/javascript'></script>
<style>
.rChart {
display: block;
margin-left: auto;
margin-right: auto;
width: 500px;
height: 500px;
}
</style>
</head>
<body >
<div id = 'chart357366a8b98' class = 'rChart dimple'></div>
<script type="text/javascript">
var opts = {
"dom": "chart357366a8b98",
"width": 500,
"height": 500,
"xAxis": {
"type": "addMeasureAxis",
"showPercent": false,
"overrideMin": -5
},
"yAxis": {
"type": "addMeasureAxis",
"showPercent": false,
"overrideMin": -0.2
},
"zAxis": [],
"colorAxis": [],
"defaultColors": [],
"layers": [],
"legend": [],
"x": "Attendees per million",
"y": "Instructors per million",
"type": "bubble",
"groups": "Country",
"id": "chart357366a8b98"
},
data = [{"Country":"Australia","Population":23737000,"Attendees":592,"Instructors":11,"Attendees per million":24.9399671399082,"Instructors per million":0.463411551586131},{"Country":"Brazil","Population":203850000,"Attendees":116,"Instructors":1,"Attendees per million":0.569045867059112,"Instructors per million":0.0049055678194751},{"Country":"Canada","Population":35675000,"Attendees":1215,"Instructors":46,"Attendees per million":34.0574632095305,"Instructors per million":1.28941836019622},{"Country":"China","Population":1368090000,"Attendees":24,"Instructors":1,"Attendees per million":0.0175427055237594,"Instructors per million":0.000730946063489975},{"Country":"Cyprus","Population":858000,"Attendees":25,"Instructors":0,"Attendees per million":29.1375291375291,"Instructors per million":0},{"Country":"Denmark","Population":5655000,"Attendees":20,"Instructors":1,"Attendees per million":3.53669319186561,"Instructors per million":0.17683465959328},{"Country":"France","Population":66092000,"Attendees":72,"Instructors":4,"Attendees per million":1.08939054651092,"Instructors per million":0.0605216970283847},{"Country":"Germany","Population":80767000,"Attendees":183,"Instructors":6,"Attendees per million":2.2657768643134,"Instructors per million":0.0742877660430621},{"Country":"Ghana","Population":27043000,"Attendees":24,"Instructors":0,"Attendees per million":0.887475501978331,"Instructors per million":0},{"Country":"India","Population":1266580000,"Attendees":0,"Instructors":1,"Attendees per million":0,"Instructors per million":0.000789527704527152},{"Country":"Ireland","Population":4609000,"Attendees":0,"Instructors":1,"Attendees per million":0,"Instructors per million":0.216966804078976},{"Country":"Israel","Population":8296000,"Attendees":0,"Instructors":1,"Attendees per million":0,"Instructors per million":0.120540019286403},{"Country":"Italy","Population":60782000,"Attendees":81,"Instructors":1,"Attendees per million":1.33263137112961,"Instructors per million":0.0164522391497483},{"Country":"Japan","Population":127020000,"Attendees":0,"Instructors":1,"Attendees per million":0,"Instructors per million":0.00787277594079673},{"Country":"Jordan","Population":6688000,"Attendees":34,"Instructors":0,"Attendees per million":5.08373205741627,"Instructors per million":0},{"Country":"Lebanon","Population":4104000,"Attendees":25,"Instructors":0,"Attendees per million":6.0916179337232,"Instructors per million":0},{"Country":"Netherlands","Population":16888000,"Attendees":39,"Instructors":0,"Attendees per million":2.30933207010895,"Instructors per million":0},{"Country":"New Zealand","Population":4560000,"Attendees":19,"Instructors":1,"Attendees per million":4.16666666666667,"Instructors per million":0.219298245614035},{"Country":"Norway","Population":5156000,"Attendees":90,"Instructors":2,"Attendees per million":17.455391776571,"Instructors per million":0.387897595034911},{"Country":"Poland","Population":38496000,"Attendees":60,"Instructors":5,"Attendees per million":1.55860349127182,"Instructors per million":0.129883624272652},{"Country":"Saudi Arabia","Population":31521000,"Attendees":20,"Instructors":0,"Attendees per million":0.634497636496304,"Instructors per million":0},{"Country":"Singapore","Population":5469000,"Attendees":0,"Instructors":1,"Attendees per million":0,"Instructors per million":0.182848784055586},{"Country":"South Africa","Population":54002000,"Attendees":90,"Instructors":2,"Attendees per million":1.66660494055776,"Instructors per million":0.0370356653457279},{"Country":"Spain","Population":46464000,"Attendees":0,"Instructors":2,"Attendees per million":0,"Instructors per million":0.0430440771349862},{"Country":"Sweden","Population":9743000,"Attendees":54,"Instructors":3,"Attendees per million":5.54244072667556,"Instructors per million":0.307913373704198},{"Country":"Switzerland","Population":8211000,"Attendees":63,"Instructors":0,"Attendees per million":7.67263427109974,"Instructors per million":0},{"Country":"Thailand","Population":64871000,"Attendees":0,"Instructors":1,"Attendees per million":0,"Instructors per million":0.015415208644849},{"Country":"United Kingdom","Population":64105000,"Attendees":1231,"Instructors":48,"Attendees per million":19.2028702909289,"Instructors per million":0.748771546681226},{"Country":"United States","Population":320354000,"Attendees":5253,"Instructors":166,"Attendees per million":16.3974852819069,"Instructors per million":0.51817676695156}];
var svg = dimple.newSvg("#" + opts.id, opts.width, opts.height);
var myChart = new dimple.chart(svg, data);
if (opts.bounds) {
myChart.setBounds(opts.bounds.x, opts.bounds.y, opts.bounds.width, opts.bounds.height);//myChart.setBounds(80, 30, 480, 330);
}
//dimple allows use of custom CSS with noFormats
if(opts.noFormats) { myChart.noFormats = opts.noFormats; };
//for markimekko and addAxis also have third parameter measure
//so need to evaluate if measure provided
//function to build axes
function buildAxis(position,layer){
var axis;
var axisopts;
if (!layer[position+"Axis"]){
axisopts = opts[position+"Axis"];
} else axisopts = layer[position+"Axis"];
if(axisopts.measure) {
axis = myChart[axisopts.type](position,layer[position],axisopts.measure);
} else {
axis = myChart[axisopts.type](position, layer[position]);
};
if(!(axisopts.type === "addPctAxis")) axis.showPercent = axisopts.showPercent;
if (axisopts.orderRule) axis.addOrderRule(axisopts.orderRule);
if (axisopts.grouporderRule) axis.addGroupOrderRule(axisopts.grouporderRule);
if (axisopts.overrideMin) axis.overrideMin = axisopts.overrideMin;
if (axisopts.overrideMax) axis.overrideMax = axisopts.overrideMax;
if (axisopts.inputFormat) axis.dateParseFormat = axisopts.inputFormat;
if (axisopts.outputFormat) axis.tickFormat = axisopts.outputFormat;
return axis;
};
var c = null;
if(d3.keys(opts.colorAxis).length > 0) {
c = myChart[opts.colorAxis.type](opts.colorAxis.colorSeries,opts.colorAxis.palette) ;
}
//allow manipulation of default colors to use with dimple
if(opts.defaultColors.length) {
opts.defaultColors = opts.defaultColors[0];
if (typeof(opts.defaultColors) == "function") {
//assume this is a d3 scale
//for now loop through first 20 but need a better way to handle
defaultColorsArray = [];
for (var n=0;n<20;n++) {
defaultColorsArray.push(opts.defaultColors(n));
};
opts.defaultColors = defaultColorsArray;
}
opts.defaultColors.forEach(function(d,i) {
opts.defaultColors[i] = new dimple.color(d);
})
myChart.defaultColors = opts.defaultColors;
}
//do series
//set up a function since same for each
//as of now we have x,y,groups,data,type in opts for primary layer
//and other layers reside in opts.layers
function buildSeries(layer, hidden){
//inherit from primary layer if not intentionally changed or xAxis, yAxis, zAxis null
if (!layer.xAxis) layer.xAxis = opts.xAxis;
if (!layer.yAxis) layer.yAxis = opts.yAxis;
if (!layer.zAxis) layer.zAxis = opts.zAxis;
var x = buildAxis("x", layer);
x.hidden = hidden;
var y = buildAxis("y", layer);
y.hidden = hidden;
//z for bubbles
var z = null;
if (!(typeof(layer.zAxis) === 'undefined') && layer.zAxis.type){
z = buildAxis("z", layer);
};
//here think I need to evaluate group and if missing do null
//as the group argument
//if provided need to use groups from layer
var s = new dimple.series(myChart, null, x, y, z, c, null, dimple.plot[layer.type], dimple.aggregateMethod.avg, dimple.plot[layer.type].stacked);
//as of v1.1.4 dimple can use different dataset for each series
if(layer.data){
//convert to an array of objects
//avoid lodash for now
datakeys = d3.keys(layer.data)
layer.dataarray = layer.data[datakeys[1]].map(function(d,i){
var tempobj = {}
datakeys.forEach(function(key){
tempobj[key] = layer.data[key][i]
})
return tempobj
})
s.data = layer.dataarray;
}
//for measure axis dimple sorts at the series level not at axis level
['x','y'].map(function(ax){
if( layer[ax + 'Axis'].type=="addMeasureAxis" && layer[ax + 'Axis'].orderRule ){
if( typeof layer[ax + 'Axis'].orderRule == "string" ){
s.addOrderRule( layer[ax + 'Axis'].orderRule );
} else if ( typeof layer[ax + 'Axis'].orderRule == "object" ) {
s._orderRules = layer[ax + 'Axis'].orderRule;
}
}
})
if(layer.hasOwnProperty("groups")) {
s.categoryFields = (typeof layer.groups === "object") ? layer.groups : [layer.groups];
//series offers an aggregate method that we will also need to check if available
//options available are avg, count, max, min, sum
}
if (!(typeof(layer.aggregate) === 'undefined')) {
s.aggregate = eval(layer.aggregate);
}
if (!(typeof(layer.lineWeight) === 'undefined')) {
s.lineWeight = layer.lineWeight;
}
if (!(typeof(layer.lineMarkers) === 'undefined')) {
s.lineMarkers = layer.lineMarkers;
}
if (!(typeof(layer.barGap) === 'undefined')) {
s.barGap = layer.barGap;
}
if (!(typeof(layer.interpolation) === 'undefined')) {
s.interpolation = layer.interpolation;
}
myChart.series.push(s);
/*placeholder fix domain of primary scale for new series data
//not working right now but something like this
//for now just use overrideMin and overrideMax from rCharts
for( var i = 0; i<2; i++) {
if (!myChart.axes[i].overrideMin) {
myChart.series[0]._axisBounds(i==0?"x":"y").min = myChart.series[0]._axisBounds(i==0?"x":"y").min < s._axisBounds(i==0?"x":"y").min ? myChart.series[0]._axisBounds(i==0?"x":"y").min : s._axisBounds(i==0?"x":"y").min;
}
if (!myChart.axes[i].overrideMax) {
myChart.series[0]._axisBounds(i==0?"x":"y")._max = myChart.series[0]._axisBounds(i==0?"x":"y").max > s._axisBounds(i==0?"x":"y").max ? myChart.series[0]._axisBounds(i==0?"x":"y").max : s._axisBounds(i==0?"x":"y").max;
}
myChart.axes[i]._update();
}
*/
return s;
};
buildSeries(opts, false);
if (opts.layers.length > 0) {
opts.layers.forEach(function(layer){
buildSeries(layer, true);
})
}
//unsure if this is best but if legend is provided (not empty) then evaluate
if(d3.keys(opts.legend).length > 0) {
var l =myChart.addLegend();
d3.keys(opts.legend).forEach(function(d){
l[d] = opts.legend[d];
});
}
//quick way to get this going but need to make this cleaner
if(opts.storyboard) {
myChart.setStoryboard(opts.storyboard);
};
myChart.draw();
</script>
<p>
Data from <a href="http://software-carpentry.org/blog/2015/02/plot-this.html" target="_blank">Software Carpentry</a>.
</p>
<p>
Code to reproduce:
<pre>
library("rCharts")
swc <- read.csv("~/swc.csv")
swc$`Attendees per million` <- with(swc, Attendees/Population/1e6)
swc$`Instructors per million` <- with(swc, Instructors/Population/1e6)
i <- dPlot(`Instructors per million`~`Attendees per million`,
data=swc, type="bubble",
groups="Country", height=500, width=500)
i$yAxis(type="addMeasureAxis", overrideMin=-.2)
i$xAxis(type="addMeasureAxis", overrideMin=-5)
i
i$publish()
</pre>
</p>
<script></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment