Skip to content

Instantly share code, notes, and snippets.

@fivetentaylor
Last active August 29, 2015 14:23
Show Gist options
  • Save fivetentaylor/754a7d6036c7c94251b1 to your computer and use it in GitHub Desktop.
Save fivetentaylor/754a7d6036c7c94251b1 to your computer and use it in GitHub Desktop.
Reservoir Sampling Viz

###Given an endless stream of random inputs, resevoir sampling allows one to uniformly sample an exact number of values from the stream

<!DOCTYPE html>
<meta charset="utf-8">
<style>
/*svg {
border: solid black 1px;
}*/
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<body></body>
<script>
var margin = {top: 120, right: 250, bottom: 120, left: 250},
width = 960 - margin.left - margin.right,
height = 540 - margin.top - margin.bottom;
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 + ")");
var random_stream_group = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 8 + ")");
var reservoir_group = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var randint = function(start, stop) {
return Math.floor(start + Math.random() * (stop - start));
};
function reservoir(svg, width, height) {
width = typeof width !== 'undefined' ? width : 400;
height = typeof height !== 'undefined' ? height : 40;
svg.append('rect')
.attr({
'width': width,
'height': height,
'x': -width/2,
'y': -height/2,
})
.style({
'fill':'rgba(0,0,0,0)',
'stroke-width':3,
'stroke':'rgb(0,0,0)',
})
function render() {
}
return render;
}
function random_stream(svg, max) {
/* NICE WAY TO SET DEFAULT VALUES */
max = typeof max !== 'undefined' ? max : 20;
var xscale = d3.scale.linear()
.domain([0,max])
.range([-width/2, width/2]);
var data = d3.range(max).map(function(){ return [randint(0,10), Math.random()] });
svg.append('line')
.attr('x1', xscale(0))
.attr('x2', xscale(max))
.attr('y1', -20)
.attr('y2', -20)
.style('stroke', 'black')
.style('stroke-width', 3);
svg.append('line')
.attr('x1', xscale(0))
.attr('x2', xscale(max))
.attr('y1', 20)
.attr('y2', 20)
.style('stroke', 'black')
.style('stroke-width', 3);
svg.append('line')
.attr('x1', xscale(0))
.attr('x2', xscale(0))
.attr('y1', 20)
.attr('y2', -20)
.style('stroke', 'red')
.style('stroke-width', 2);
svg.append('line')
.attr('x1', xscale(1))
.attr('x2', xscale(1))
.attr('y1', 20)
.attr('y2', -20)
.style('stroke', 'red')
.style('stroke-width', 2);
function render() {
data.push([randint(0, 10), Math.random()]);
if( data.length > max ) {
data.shift();
}
// DATA JOIN
var t = svg.selectAll('text')
.data(data, function(d){ return d; })
// UPDATE
t.transition()
.attr('x', function(d,i){ return xscale(i + 0.5) });
// ENTER
t.enter()
.append('text')
.attr("text-anchor", "middle")
.attr('dy', '.35em')
.attr('font-size', 40)
.text(function(d){ return d[0]; })
.attr('x', 1000)
.transition()
.attr('x', function(d,i){ return xscale(i + 0.5); });
// EXIT
t.exit()
.transition()
.attr('x', -1000)
.remove();
}
return render;
}
var render = random_stream(random_stream_group, 19);
reservoir(reservoir_group)();
window.setInterval(render, 1000);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment