An example of K-means clustering in d3.js.
xxxxxxxxxx
<meta charset="utf-8">
<style>
body {
width: 1024px;
margin-top: 0;
margin: auto;
font-family: "Lato", "PT Serif", serif;
color: #222222;
padding: 0;
font-weight: 300;
line-height: 33px;
-webkit-font-smoothing: antialiased;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.dot {
stroke: #eee;
}
.centroid{
stroke: #000;
fill-opacity: 0.8;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="model.js"></script>
<script>
var margin = {top: 100, right: 20, bottom: 80, left: 20},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
translate_speed = 1000;
var color = d3.scale.category10();
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 x = d3.scale.linear()
.range([0, width])
.domain([0, 50]).nice();
var y = d3.scale.linear()
.range([height, 0])
.domain([0,50]).nice();
svg.append('text')
.attr('x', width )
.attr('y', height +50)
.attr('class', 'status')
.text('Clusters: ')
.style('text-anchor', 'end')
.style('font-size', '20')
svg.append('text')
.attr('x', width/2 )
.attr('y', -50)
.attr('class', 'step')
.text('Initialize clusters.')
.style('text-anchor', 'middle')
.style('font-size', '36')
function initialize(){
// Set the number of clusters
var num_clusters = Math.floor(Math.random()*4)+2;
// Generate a random sample of points
var samples = d3.range(0,40).map(function(d){
return [ Math.floor(Math.random()*50), Math.floor(Math.random()*50)]
})
// Update View
d3.select('.status').text('Clusters: '+num_clusters)
// Initialize the model
var k = new kmeans(num_clusters, samples)
// Plot this first round
plot(k)
return k
}
function plot(k){
svg.selectAll('g').remove()
var g = svg.append('g');
g.selectAll(".dot")
.data(k.data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 5)
.attr("cx", function(d) { return x(d.x); })
.attr("cy", function(d) { return y(d.y); })
.style("fill", function(d) { return color(d.clusterNumber); })
g.selectAll(".centroids")
.data(k.centroids)
.enter().append('rect')
.attr('class', 'centroid')
.attr("x", function(d) { return x(d.x) - 2.5; })
.attr("y", function(d) { return y(d.y) - 2.5; })
.attr('width', 20)
.attr('height', 20)
.attr('rx', 1)
.attr('ry', 1)
.style("fill", function(d, i) { return color(i); })
}
function step(k){
k.recalculate_centroids()
k.update_clusters()
plot(k)
}
function run(){
var k = initialize(),
max_count = 100,
updates = 0;
var go = setInterval(function(){
if (k.isStillMoving == 1) {
d3.select('.step').text('Assign and Update ('+updates+').')
step(k)
updates +=1
}else{
clearInterval(go)
d3.selectAll('circles').transition().duration(translate_speed).remove()
run()
};
}, translate_speed)
}
run()
d3.select(self.frameElement).style("height", (height+margin.top+margin.bottom) + "px");
</script>
https://d3js.org/d3.v3.min.js