Skip to content

Instantly share code, notes, and snippets.

@plmrry
Created March 15, 2016 20:31
Show Gist options
  • Save plmrry/a3974fa53a6e77e8e785 to your computer and use it in GitHub Desktop.
Save plmrry/a3974fa53a6e77e8e785 to your computer and use it in GitHub Desktop.
High-Dimensional Crawler

A randomly-generated five-dimensional dataset is shown projected onto two dimensions according to the vector sum of five arbitrary vectors. This technique is identical to Star Coordinates by Eser Kandogan.

At each step in this animation, a dimension is chosen at random, and the vector representing that dimension is moved in a random direction.

<!DOCTYPE html>
<html>
<head>
<title>High-Dimensional Crawler</title>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css">
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-11">
<div id="chart"></div>
</div>
</div>
</div>
<script>
/**
* Note: This was compiled from CoffeeScript, so it's messy :..(
*/
var generateData, selection, stretchChart;
stretchChart = function() {
var radius, theChart;
console.info("Inside stretchChart()");
radius = 5;
theChart = function(selection) {
console.info("Inside theChart()");
return selection.each(function(data, index) {
var clickButton,
clickVar,
drag,
gs,
height, margin, outerG, outerHeight, outerWidth,
pointSetGs, points, scale, setTranslate, svg,
tColorScale, tExtent, tSizeScale, width, xScale, yScale;
console.log($(this).parent().width());
console.info("Acting on the DOM object: " + this.tagName + " #" + this.getAttribute('id'));
margin = {
top: 20,
right: 20,
bottom: 20,
left: 20
};
outerWidth = $(this).parent().width();
outerHeight = 500;
width = outerWidth - margin.left - margin.right;
height = outerHeight - margin.top - margin.bottom;
data.map(function(each) {
return each.foo = "bar";
});
tExtent = d3.extent(data, function(each) {
return each.t;
});
tColorScale = d3.scale.log().domain(tExtent).range(["#000", "#333"]);
tSizeScale = d3.scale.linear().domain(tExtent).range([1, 5]);
svg = d3.select(this).data([data]).append("svg").attr("width", width + margin.left + margin.right).attr("height", height + margin.top + margin.bottom);
outerG = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
outerG.append("rect").attr({
width: width,
height: height
}).style({
// "stroke": "#ccc",
"fill": "none"
});
scale = d3.scale.linear();
xScale = scale.range([margin.left, width - margin.right]);
yScale = scale.copy().range([height - margin.right, margin.top]);
setTranslate = function(d) {
return "translate( " + d.x + ", " + d.y + ")";
};
pointSetGs = outerG.selectAll("g.pointSet").data(function(d) {
return d;
}).enter().append("g").classed("pointSet", true).each(function(d) {
d.x = xScale(0.5);
return d.y = yScale(0.5);
});
gs = pointSetGs.append("g").classed("point", true).attr("transform", setTranslate);
points = gs.append("circle").attr("r", function(d) {
return tSizeScale(d.t);
}).style("fill", function(d) {
return tColorScale(d.t);
}).style("fill-opacity", 0.1);
drag = d3.behavior.drag().origin(function(d) {
return d;
});
function moveRand(val) {
d3.selectAll("g.point").each(function(data) {
data._x = data.x;
return data._y = data.y;
});
var random_var = d3.shuffle(["t", "v1", "v2", "v3", "v4"])[0];
var dat = gs.data().filter(function(d) { return d[random_var] > 95; });
var random_point = d3.shuffle(dat)[0];
var random = function() {
var a = 200;
return Math.random() * a - a/2;
}
var dx = xScale(0.5) + random();
var dy = yScale(0.5) + random();
gs.filter(function(d) { return d === random_point })
.each(moved(dx, dy, random_var));
}
function moved(x, y, varName) {
return function(d) {
var dxScale, dyScale, v;
v = d[varName];
dxScale = (x - d._x) / v;
dyScale = (y - d._y) / v;
d3.transition().duration(700)
.each(function(t) {
gs.each(function(data) {
var w;
w = data[varName];
data.x = data._x + dxScale * w;
data.y = data._y + dyScale * w;
})
.transition()
.attr("transform", setTranslate)
})
.each("end", function() {
moveRand(10);
})
}
}
moveRand(10);
});
};
return theChart;
};
generateData = function() {
var b0, b1, b2, b3, b4, data, getPredictor, mapData, n, _ref;
n = 1000;
_ref = [0, 1, 1, 1, 1], b0 = _ref[0], b1 = _ref[1], b2 = _ref[2], b3 = _ref[3], b4 = _ref[4];
getPredictor = function() {
// return Math.floor(Math.random() * 100);
return d3.random.normal(50, 30)();
};
mapData = function() {
var mean, t, v1, v2, v3, v4, _ref1;
_ref1 = d3.range(4).map(getPredictor), v1 = _ref1[0], v2 = _ref1[1], v3 = _ref1[2], v4 = _ref1[3];
mean = b0 + (b1 * v1) + (b2 * v2) + (b3 * v3) + (b4 * v4);
t = d3.random.normal(mean)();
return {
v1: v1,
v2: v2,
v3: v3,
v4: v4,
t: t
};
};
return data = d3.range(n).map(mapData);
};
generateData();
selection = d3.select("#chart").datum(generateData);
stretchChart()(selection);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment