Skip to content

Instantly share code, notes, and snippets.

@ctufts
Last active September 7, 2018 13:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ctufts/47d9de58c947966701c52a2a31f4a507 to your computer and use it in GitHub Desktop.
Save ctufts/47d9de58c947966701c52a2a31f4a507 to your computer and use it in GitHub Desktop.
Normal Distribution Probability Density Block
license: mit
height: 600
border: no

This block is an interactive visualization of the probability density function of a normal distribution. By adjusting the slider bars you can see how the mean and standard deviation parameters effect the distribution shape.

<!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>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/rangeslider.js/2.3.0/rangeslider.min.js"></script>
<link rel="stylesheet" type="text/css" href="main.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/rangeslider.js/2.3.0/rangeslider.css">
<link href="https://fonts.googleapis.com/css?family=Roboto+Slab" rel="stylesheet">
</head>
<body>
<div id=meanDiv>
<p id=meanValDisplay></p>
<input id="meanSlider" class="paramSlider" type="range" min="-3" max="3" step="0.1" value="0" data-orientation="vertical" >
</div>
<div id=sdDiv>
<p id=sdValDisplay></p>
<input id="sdSlider" class="paramSlider" type="range" min="1" max="3" step="0.1" value="1" data-orientation="vertical" >
</div>
<p></p>
<script>
var numDataPoints = 1000;
var interval = 0.05
var upper_bound = 10.0;
var lower_bound = -10.0;
var mean = 0;
var std = 1;
var margin = {top: 20, right: 10, bottom: 20, left: 40};
var width = 960 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
//create data points
var sdLabel = "Standard Deviation: " + std;
var meanLabel = "Mean: " + mean;
document.getElementById("meanValDisplay").innerHTML = meanLabel;
document.getElementById("sdValDisplay").innerHTML = sdLabel;
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]);
/////// Define Axis //////////////////////////////
var xAxis = d3.axisBottom()
.scale(xScale);
var yAxis = d3.axisLeft()
.scale(yScale)
.ticks(8);
// create svg
// var svg = d3.select("body")
// .append("svg")
// .attr("width", w)
// .attr("height", h);
var svg = d3.select("body").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 + ")");
// append data points
svg.append("g")
.attr("id", "circles")
// .attr("clip-path", "url(#chart-area)")
.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);
// 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");;
d3.selectAll(".paramSlider")
.on("input", function(){
var mean = d3.select('#meanSlider').property('value');
var std = d3.select('#sdSlider').property('value');
var sdLabel = "Standard Deviation: " + std;
var meanLabel = "Mean: " + mean;
document.getElementById("meanValDisplay").innerHTML = meanLabel;
document.getElementById("sdValDisplay").innerHTML = sdLabel;
// create new data
// dataset = create_data(numDataPoints);
var dataset = create_data(interval, upper_bound, lower_bound, mean, std);
var dur = 50;
//Update scale domains
xScale.domain([d3.min(dataset, function(d) {
return d.x;
}),
d3.max(dataset, function(d) {
return d.x;
})
]);
yScale.domain([
d3.min(dataset, function(d) {
return d.y;
}),
d3.max(dataset, function(d) {
return d.y;
})
]);
// update data points
svg.selectAll("circle")
.data(dataset)
.transition()
.duration(dur)
.attr("cx", function(d) {
return xScale(d.x);
})
.attr("cy", function(d) {
return yScale(d.y);
});
// update axis
svg.select(".x.axis")
.transition()
.duration(dur)
.call(xAxis);
svg.select(".y.axis")
.transition()
.duration(dur)
.call(yAxis);
});
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>
p{
font-family: 'Roboto Slab', serif;
}
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-size: 10px;
font-family: 'Roboto Slab', serif;
}
.text-label {
font-size: 10px;
font-family: 'Roboto Slab', serif;
/*font-family: sans-serif;*/
}
.dot {
stroke: #293b47;
fill: #7A99AC
}
#ex1Slider .slider-selection {
background: #BABABA;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment