Skip to content

Instantly share code, notes, and snippets.

@gabrielflorit
Last active October 1, 2016 04:44
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 gabrielflorit/32494d816b9c39c81f3533dee11322d0 to your computer and use it in GitHub Desktop.
Save gabrielflorit/32494d816b9c39c81f3533dee11322d0 to your computer and use it in GitHub Desktop.
Sampling distribution
license: mit
height: 450
border: no
body{font-family:sans-serif}.intro{margin:0 1em}span.label{display:inline-block;text-align:center;font-weight:700;width:2.75em}span.group{display:inline-block;white-space:nowrap}input{position:relative;top:2px;width:12em}text{font:10px sans-serif}svg{display:block}.bar rect{fill:#4682b4;shape-rendering:crispEdges}
var margin={top:30,right:30,bottom:30,left:30},width=960-margin.left-margin.right,height=240-margin.top-margin.bottom,populationSize=1e4,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+")"),x=d3.scaleLinear().range([0,width]),y=d3.scaleLinear().range([height,0]),updateRangeOutput=function(t,e){return document.querySelector(t).parentNode.querySelector("output").textContent=e},updateElement=function(t,e){return document.querySelector(t).textContent=e},drawData=function(){var t=document.querySelector("input.proportion").value,e=document.querySelector("input.samples").value,a=document.querySelector("input.size").value;updateElement("span.proportion",d3.format(".0%")(t)),updateElement("span.samples",d3.format(",")(e)),updateElement("span.size",d3.format(",")(a));var n=d3.range(populationSize).map(function(e,a,n){return a<t*n.length?1:0}),r=d3.range(e).map(function(t){var e=d3.shuffle(n).slice(0,a);return d3.mean(e)}),i=d3.histogram().domain(x.domain()).thresholds(x.ticks(Math.min(100,a)))(r);y.domain([0,d3.max(i,function(t){return t.length})]),svg.selectAll("*").remove();var o=svg.selectAll(".bar").data(i).enter().append("g").attr("class","bar").attr("transform",function(t){return"translate("+x(t.x0)+", "+y(t.length)+")"});o.append("rect").attr("x",0).attr("width",function(t){return x(t.x1)-x(t.x0)}).attr("height",function(t){return height-y(t.length)}),svg.append("g").attr("class","axis axis--x").attr("transform","translate(0, "+height+")").call(d3.axisBottom(x))};d3.selectAll("input").on("input",function(t){return drawData()}),drawData();
<!DOCTYPE html>
<title>Sampling distribution</title>
<link href='dist.css' rel='stylesheet' />
<body>
<div class='intro'>
<p>Given a population where <i>p</i> = <span class="group"><span class="proportion label"></span><input class="proportion" type="range" min="0" max="1" step="0.01" value="0.2" /></span>,</p>
<p>draw
a histogram of <span class="group"><span class="samples label"></span> sample proportions<input class="samples" type="range" min="1" max="1000" step="1" value="200" /></span></p>
<p>where the samples are of
size <span class="group"><i>n</i> = <span class="size label"></span><input class="size" type="range" min="1" max="1000" step="1" value="100" /></span>.</p>
<p>We call this a <b>sampling distribution</b>.</p>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src='dist.js'></script>
</body>
// Create margins.
const margin = { top: 30, right: 30, bottom: 30, left: 30 }
const width = 960 - margin.left - margin.right
const height = 240 - margin.top - margin.bottom
const populationSize = 10000
// Create svg.
const 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})`)
// Create scales.
const x = d3.scaleLinear().range([0, width])
const y = d3.scaleLinear().range([height, 0])
// Helper function to update range output
const updateRangeOutput = (selector, value) =>
document.querySelector(selector).parentNode.querySelector('output')
.textContent = value
const updateElement = (selector, value) =>
document.querySelector(selector).textContent = value
const drawData = () => {
// Get adjustable parameters.
const proportion = document.querySelector('input.proportion').value
const samples = document.querySelector('input.samples').value
const size = document.querySelector('input.size').value
// Update parameters next to sliders.
// updateRangeOutput('input.proportion', d3.format('.0%')(proportion))
updateElement('span.proportion', d3.format('.0%')(proportion))
// updateRangeOutput('input.population', d3.format(',')(populationSize))
// updateRangeOutput('input.samples', d3.format(',')(samples))
updateElement('span.samples', d3.format(',')(samples))
// updateRangeOutput('input.size', d3.format(',')(size))
updateElement('span.size', d3.format(',')(size))
// Create the population.
const population = d3.range(populationSize)
.map((v, index, array) => index < proportion * array.length ? 1 : 0)
// For a total of `samples` trials,
const data = d3.range(samples)
.map(v => {
// create a random sample of size `size`,
const sample = d3.shuffle(population).slice(0, size)
// and return mean.
return d3.mean(sample)
})
// Bin data.
const bins = d3.histogram()
.domain(x.domain())
.thresholds(x.ticks(Math.min(100, size)))
(data)
// Set y-scale based on data.
y.domain([0, d3.max(bins, d => d.length)])
// Remove all elements.
svg.selectAll('*').remove()
// Draw data.
const bar = svg.selectAll('.bar')
.data(bins)
.enter().append('g')
.attr('class', 'bar')
.attr('transform', d => `translate(${x(d.x0)}, ${y(d.length)})`)
// Draw bars.
bar.append('rect')
.attr('x', 0)
.attr('width', d => x(d.x1) - x(d.x0))
.attr('height', d => height - y(d.length))
// Draw axis.
svg.append('g')
.attr('class', 'axis axis--x')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(x))
}
d3.selectAll('input').on('input', d => drawData())
drawData()
body
font-family sans-serif
.intro
margin 0 1em
span.label
display inline-block
text-align center
font-weight bold
width 2.75em
span.group
display inline-block
white-space nowrap
input
position relative
top 2px
width 12em
text
font 10px sans-serif
svg
display block
.bar rect
fill steelblue
shape-rendering crispEdges
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment