Skip to content

Instantly share code, notes, and snippets.

@TommyCoin80
Last active August 11, 2017 13:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TommyCoin80/ea47bc62c09c91cbbc604c02b73f4b23 to your computer and use it in GitHub Desktop.
Save TommyCoin80/ea47bc62c09c91cbbc604c02b73f4b23 to your computer and use it in GitHub Desktop.
D3.Unconf Badge
license: mit
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<link href='https://fonts.googleapis.com/css?family=Play' rel='stylesheet' type='text/css'>
<style>
body {
margin:auto;
font-family: 'Play', sans-serif;
font-size:100%;
}
text {
font-family: 'Play', sans-serif;
}
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var WeibullPlot = function(opts) {
var margin = opts.margin || {top: 320, right: 30, bottom: 260, left: 70};
var height = opts.height || 920;
var width = opts.width || 900;
var dur = opts.duration || 3000;
var del = opts.delay || 250;
var ease = opts.ease || d3.easeLinear;
var s = {};
//Prep Data
var data = {};
data.gridLines = {
x: [1].concat(d3.range(3,49,3)),
y: d3.range(.01,1,.01)
};
data.gridLabels = {
x: [3, 12, 24, 36],
y: [.01, .05, .10, .25, .50, .75, .99]
};
data.points = [];
data.points.push({x:1,y:0.0296});
data.points.push({x:2,y:0.0496});
data.points.push({x:3,y:0.089});
data.points.push({x:4,y:0.099});
data.points.push({x:5,y:0.1199});
data.points.push({x:6,y:0.1599});
data.points.push({x:7,y:0.18});
data.points.push({x:8,y:0.1899});
data.points.push({x:9,y:0.215});
data.points.push({x:10,y:0.225});
data.points.push({x:11,y:0.2375});
data.points.push({x:12,y:0.265});
data.regCoeffs = lsReg(
data.points.map(function(d) { return xWeib(d.x)}),
data.points.map(function(d) { return yWeib(d.y)})
);
data.regLine = data.gridLines.x.map(function(d) {
return {
x: xWeib(d),
y: xWeib(d)*data.regCoeffs[0] + data.regCoeffs[1]
}
});
// Set Scales
var scale = {};
scale.x = d3.scaleLinear()
.range([0,width])
.domain(d3.extent(data.gridLines.x));
scale.y = d3.scaleLinear()
.range([height,0])
.domain(d3.extent(data.gridLines.y));
// Draw
s.svg = d3.select("#" + opts.elementId)
.append("svg")
.attr("height", height + margin.top + margin.bottom)
.attr("width", width + margin.left + margin.right)
.style("-webkit-user-select","none")
.style("cursor","default");
s.chart = s.svg.append("g")
.attr("transform","translate(" + margin.left + "," + margin.top + ")");
// Draw Grid
s.gridLines = {};
s.gridLabels = {};
s.gridLines.y = s.chart.selectAll(".yLines")
.data(data.gridLines.y)
.enter()
.append("line")
.attr("x1",0)
.attr("x2",width)
.attr("y1", function(d) { return scale.y(d)})
.attr("y2", function(d) { return scale.y(d)})
.style("stroke-opacity", function(d) { return (data.gridLabels.y.indexOf(+d3.format(".2")(d))<0)?.20:.55; })
.style("stroke","black");
s.gridLabels.y = s.chart.selectAll(".yLabels")
.data(data.gridLabels.y)
.enter()
.append("text")
.attr("x",0)
.attr("y", function(d) { return scale.y(d)})
.attr("text-anchor","end")
.attr("dx",-2)
.style("font-size",".8em")
.text(function(d) { return d3.format('.2p')(d) });
s.gridLines.x = s.chart.selectAll(".xLines")
.data(data.gridLines.x)
.enter()
.append("line")
.attr("x1",function(d) { return scale.x(d)})
.attr("x2",function(d) { return scale.x(d)})
.attr("y1", 0)
.attr("y2", height)
.style("stroke-opacity", function(d) { return (data.gridLabels.x.concat([1,48]).indexOf(d)<0)?.20:.55; })
.style("stroke","black");
s.gridLabels.x = s.chart.selectAll(".xLabels")
.data(data.gridLabels.x)
.enter()
.append("text")
.attr("y",height)
.attr("x", function(d) { return scale.x(d)})
.attr("text-anchor","start")
.attr("dy",16)
.style("font-size",".8em")
.text(function(d) { return d + ' months'});
// Draw Legend
(function() {
var km = s.chart.append("g")
.attr("transform","translate(" + width*(2/7) + "," + (height + 30) + ")");
km.append("rect")
.attr("height",30)
.attr("width", width/7)
.style("fill","#d11141" )
.attr("rx",4)
.style("stroke","gray");
km.append("text")
.style("text-anchor","middle")
.attr("dy","1.25em")
.attr("dx", +km.select("rect").attr("width")/2)
.text("Kaplan-Meier")
.style("fill","white");
var wf = s.chart.append("g")
.attr("transform","translate(" + width*(4/7) + "," + (height + 30) + ")");
wf.append("rect")
.attr("height",30)
.attr("width", width/7)
.style("fill","#00aedb" )
.attr("rx",4)
.style("stroke","gray");
wf.append("text")
.style("text-anchor","middle")
.attr("dy","1.25em")
.attr("dx", +wf.select("rect").attr("width")/2)
.text("Weibull")
.style("fill","white");
})();
drawKM();
// Draw KM Line
function drawKM() {
var line = d3.line()
.x(function(d) { return scale.x(d.x)})
.y(function(d) { return scale.y(d.y)})
.curve(d3.curveStepAfter);
s.kmLine = s.chart.selectAll(".dataPoint")
.data([data.points])
.enter()
.append("path")
.attr("d", line)
.style("stroke-opacity",1)
.style("stroke","#d11141")
.style("stroke-width",1.5)
.style("fill","none")
.each(function(d) {
var tl = this.getTotalLength();
var s = d3.select(this);
s.attr("stroke-dasharray", tl + " " + tl)
.attr("stroke-dashoffset", tl)
.transition()
.duration(dur)
.delay(del)
.attr("stroke-dashoffset", 0)
.on("end", function() {
s.attr("stroke-dasharray","0 0");
weibullSpace();
})
})
}
// Transform Spacing
function weibullSpace() {
scale.x.domain([xWeib(1),xWeib(48)]);
scale.y.domain([yWeib(.01),yWeib(.99)]);
var line = d3.line()
.x(function(d) { return scale.x(xWeib(d.x))})
.y(function(d) { return scale.y(yWeib(d.y))})
.curve(d3.curveStepAfter);
s.gridLines.y.transition()
.duration(dur)
.ease(ease)
.delay(del)
.attr("y1", function(d) { return scale.y(yWeib(d))})
.attr("y2", function(d) { return scale.y(yWeib(d))});
s.gridLines.x.transition()
.duration(dur)
.ease(ease)
.delay(del)
.attr("x1", function(d) { return scale.x(xWeib(d))})
.attr("x2", function(d) { return scale.x(xWeib(d))});
s.gridLabels.y.transition()
.duration(dur)
.ease(ease)
.delay(del)
.attr("y", function(d) { return scale.y(yWeib(d));});
s.gridLabels.x.transition()
.duration(dur)
.ease(ease)
.delay(del)
.attr("x", function(d) { return scale.x(xWeib(d));});
s.kmLine.transition()
.duration(dur)
.ease(ease)
.delay(del)
.attr("d", line)
.on("end", drawRegLine);
}
// Draw straight regression Line
function drawRegLine() {
var line = d3.line()
.x(function(d) { return scale.x(d.x)})
.y(function(d) { return scale.y(d.y)})
.curve(d3.curveBasis)
s.regLine = s.chart.selectAll(".regLine")
.data([data.regLine])
.enter()
.append("path")
.attr("d", line)
.style("stroke","#00aedb")
.style("stroke-width",1.5)
.style("fill","none")
.each(function(d) {
var tl = this.getTotalLength();
var l = d3.select(this)
l.attr("stroke-dasharray", tl + " " + tl)
.attr("stroke-dashoffset", tl)
.transition()
.duration(dur)
.delay(del)
.attr("stroke-dashoffset", 0)
.on("end", function() {
l.attr("stroke-dasharray","0 0");
normalSpace();
})
})
}
// Transform Spacing
function normalSpace() {
scale.x.domain(d3.extent(data.gridLines.x));
scale.y.domain(d3.extent(data.gridLines.y));
var line = d3.line()
.x(function(d) { return scale.x(d.x)})
.y(function(d) { return scale.y(d.y)})
.curve(d3.curveStepAfter);
var regLine = d3.line()
.x(function(d) { return scale.x(xUnweib(d.x))})
.y(function(d) { return scale.y(yUnweib(d.y))})
.curve(d3.curveBasis);
s.gridLines.y.transition()
.duration(dur)
.ease(ease)
.delay(del)
.attr("y1", function(d) { return scale.y(d)})
.attr("y2", function(d) { return scale.y(d)});
s.gridLines.x.transition()
.duration(dur)
.ease(ease)
.delay(del)
.attr("x1", function(d) { return scale.x(d)})
.attr("x2", function(d) { return scale.x(d)});
s.gridLabels.y.transition()
.duration(dur)
.ease(ease)
.delay(del)
.attr("y", function(d) { return scale.y(d);});
s.gridLabels.x.transition()
.duration(dur)
.ease(ease)
.delay(del)
.attr("x", function(d) { return scale.x(d);});
s.kmLine.transition()
.duration(dur)
.ease(ease)
.delay(del)
.attr("d", line);
s.regLine.transition()
.duration(dur)
.ease(ease)
.delay(del)
.attr("d", regLine)
.on("end", reset)
}
// Reset the chart and start again
function reset() {
s.kmLine.transition()
.duration(dur)
.ease(ease)
.delay(del)
.style("opacity",0)
.transition()
.duration(dur)
.ease(ease)
.remove();
s.regLine.transition()
.duration(dur)
.ease(ease)
.delay(del)
.style("opacity",0)
.transition()
.duration(dur)
.ease(ease)
.remove()
.on("end", drawKM)
}
function xWeib(x) {
return Math.log(x);
}
function yWeib(y) {
return Math.log(Math.log(1/(1 - y)));
}
function xUnweib(x) {
return Math.pow(Math.E,x);
}
function yUnweib(y) {
return 1 -1/Math.pow(Math.E,Math.pow(Math.E,y));
}
function lsReg(X,Y) {
var meanX = d3.mean(X),
meanY = d3.mean(Y);
var ssXX = d3.sum(X.map(function(d) { return Math.pow(d - meanX, 2); })),
ssYY = d3.sum(Y.map(function(d) { return Math.pow(d - meanY, 2); }));
var ssXY = d3.sum(X.map(function(d, i) { return (d - meanX) * (Y[i] - meanY);}))
var slope = ssXY / ssXX;
var intercept = meanY - (meanX * slope);
return [slope, intercept];
}
}
</script>
<div id="chart"></div>
<script>
WeibullPlot({elementId:"chart"});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment