Skip to content

Instantly share code, notes, and snippets.

@ctufts
Last active March 9, 2017 20:38
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save ctufts/a90019910166d8378c6462dfd2f6f3ec to your computer and use it in GitHub Desktop.
Normal Distribution CDF value based on standard deviations
license: mit
border: no
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Probability Density: Normal Distribution</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdn.jsdelivr.net/jstat/latest/jstat.min.js"></script>
<link rel="stylesheet" type="text/css" href="main.css">
<link href="https://fonts.googleapis.com/css?family=Roboto+Slab" rel="stylesheet">
</head>
<body>
<div id="chartdiv"></div>
<script>
var bisectX = d3.bisector(function(d) {
return d.x;
}).left;
var pct = d3.format('02.2f');
var numDataPoints = 1000;
var interval = 0.05
var upper_bound = 3.1;
var lower_bound = -3.0;
var mean = 0;
var std = 1;
var margin = {
top: 50,
right: 20,
bottom: 50,
left: 50
};
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var svg = d3.select("#chartdiv").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var dataset = create_data(interval, upper_bound, lower_bound, mean, std);
////// Define Scales /////////////////
var xScale = d3.scaleLinear()
.domain([d3.min(dataset, function(d) {
return d.x;
}), d3.max(dataset, function(d) {
return d.x;
})])
.range([0, width]);
var yScale = d3.scaleLinear()
.domain([
d3.min(dataset, function(d) {
return (d.y);
}),
d3.max(dataset, function(d) {
return d.y;
})
])
.range([height, 0]);
var area = d3.area()
.x(function(d) {
return xScale(d.x);
})
.y1(function(d) {
return yScale(d.y);
});
var xlabels = ['-3\u03C3', '-2\u03C3', '-\u03C3',
'0', '\u03C3', '2\u03C3', '3\u03C3'
];
/////// Define Axis //////////////////////////////
var xAxis = d3.axisBottom()
.scale(xScale)
.ticks(xlabels.length)
.tickFormat(function(d, i) {
return xlabels[i];
});
var yAxis = d3.axisLeft()
.scale(yScale)
.ticks(8);
// append data points
svg.append("g")
.attr("id", "circles")
.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("class", "dot")
.attr("cx", function(d) {
return xScale(d.x);
})
.attr("cy", function(d) {
return yScale(d.y);
})
.attr("r", 3.0)
area.y0(yScale(0));
// cut off datapoints that are outside the axis
svg.append("clipPath")
.attr("id", "chart-area")
.append("rect")
.attr("width", width)
.attr("height", height);
// Set area coverage to x-axis 0 position, i.e. 1/2 dataset
svg.append("path")
.data([dataset.slice(0, Math.floor(dataset.length / 2))])
.attr("clip-path", "url(#chart-area)")
.attr("class", "area")
.attr("fill", "steelblue")
.attr("d", area);
svg.append("text")
.attr("id", "pdisplay")
.attr("x", xScale(0))
.attr("y", yScale(0.2))
.style("text-anchor", "middle")
.text("p(X \u2264 x) = 0.50");
var focus = svg.append("g")
.attr("class", "focus")
.style("display", "inline");
focus.append("circle")
.attr("r", 4.5);
// Set up focus (container for vertical guiding line)
var center_point = dataset[Math.floor(dataset.length / 2) - 1];
focus.attr("transform", "translate(" + xScale(center_point.x) +
"," + yScale(center_point.y) + ")");
focus.append("line")
.attr('x1', 0)
.attr('x2', 0)
.attr('y1', 0)
.attr('y2', height - yScale(center_point.y));;
// rect for tracking mouse (active over dimensions of svg )
svg.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)
.on("mouseover", function() {
focus.style("display", null);
})
.on("mouseout", function() {
focus.style("display", "inline");
})
.on("mousemove", mousemove);
// append Axes ///////////////////////////
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("x", -10)
.attr("dy", "0.71em")
.attr("fill", "#000")
.text("Probability Density");;
function mousemove() {
var x0 = xScale.invert(d3.mouse(this)[0]),
i = bisectX(dataset, x0, 1),
d0 = dataset[i - 1],
d1 = dataset[i],
d = x0 - d0.x > d1.x - x0 ? d1 : d0;
focus.attr("transform", "translate(" + xScale(d.x) + "," + yScale(d.y) + ")");
focus.select('line')
.attr('x1', 0)
.attr('x2', 0)
.attr('y1', 0)
.attr('y2', height - yScale(d.y));
// // Update the 'area to go with the line'
svg.select("path")
.data([dataset.slice(0, dataset.indexOf(d) + 1)])
.attr("d", area);
// Update center display
svg.select("#pdisplay").text('p(X \u2264 x) = ' + pct(jStat.normal.cdf(d.x, mean, std)));
}
function create_data(interval, upper_bound, lower_bound, mean, std) {
var n = Math.ceil((upper_bound - lower_bound) / interval)
var data = [];
x_position = lower_bound;
for (i = 0; i < n; i++) {
data.push({
"y": jStat.normal.pdf(x_position, mean, std),
"x": x_position
})
x_position += interval
}
return (data);
}
</script>
</body>
</html>
.focus line {
stroke: #E4002B;
/*fill: none;*/
stroke-width: 3;
}
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-size: 14px;
font-family: 'Roboto Slab', serif;
}
.dot {
stroke: #293b47;
fill: #7A99AC
}
.overlay {
fill: none;
pointer-events: all;
}
.focus circle {
fill: none;
stroke: steelblue;
}
.area {
opacity: 0.2;
}
#chartdiv {
width:960px;
height: 500px;
}
#pdisplay{
font-size: 26px;
font-family: 'Roboto Slab', serif;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment