script.js
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
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})`)
const x = d3.scaleLinear().range([0, width])
const y = d3.scaleLinear().range([height, 0])
const updateRangeOutput = (selector, value) =>
document.querySelector(selector).parentNode.querySelector('output')
.textContent = value
const updateElement = (selector, value) =>
document.querySelector(selector).textContent = value
const drawData = () => {
const proportion = document.querySelector('input.proportion').value
const samples = document.querySelector('input.samples').value
const size = document.querySelector('input.size').value
updateElement('span.proportion', d3.format('.0%')(proportion))
updateElement('span.samples', d3.format(',')(samples))
updateElement('span.size', d3.format(',')(size))
const population = d3.range(populationSize)
.map((v, index, array) => index < proportion * array.length ? 1 : 0)
const data = d3.range(samples)
.map(v => {
const sample = d3.shuffle(population).slice(0, size)
return d3.mean(sample)
})
const bins = d3.histogram()
.domain(x.domain())
.thresholds(x.ticks(Math.min(100, size)))
(data)
y.domain([0, d3.max(bins, d => d.length)])
svg.selectAll('*').remove()
const bar = svg.selectAll('.bar')
.data(bins)
.enter().append('g')
.attr('class', 'bar')
.attr('transform', d => `translate(${x(d.x0)}, ${y(d.length)})`)
bar.append('rect')
.attr('x', 0)
.attr('width', d => x(d.x1) - x(d.x0))
.attr('height', d => height - y(d.length))
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()
dist.js
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();