I have already a code for drawing parallel coordinates, that works just fine. I can draw a parallel coordinates for some features (label, feature1, feature2, ..., feature5
: some specific columns of my database).
In my test input file, the values of label
feature are either 1, 2, or 3. Now, I want to remove label
axis and instead use 3 colors to color-code the parallel coordinates visualization. I don't know how to do that. I will be thankful if you can help me.
var m = [30, 10, 10, 10],
w = 800 - m[1] - m[3],
h = 500 - m[0] - m[2];
var x = d3.scale.ordinal().rangePoints([0, w], 1),
y = {},
dragging = {};
var line = d3.svg.line(),
axis = d3.svg.axis().orient("left"),
background,
foreground;
var svg = d3.select("body").append("svg:svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("svg:g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")");
// Input data (test.csv) is in this link : http://pastebin.com/raw.php?i=8nTGRenj
d3.csv("test.csv").row(function (d) {
return {
// Features that are needed to be visualize
label: d.label,
feature1: d.feature1,
feature2: d.feature2,
feature3: d.feature3,
feature4: d.feature4,
feature5: d.feature5
};
})
.get(function (e, data) {
x.domain(
dimensions = d3.keys(data[0])
.filter(function (d) {
if (d == "label") {
y[d] = d3.scale.linear()
.domain(d3.extent(data, function (p) {
return +p[d];
}))
.range([h, 0]);
} else {
y[d] = d3.scale.linear()
.domain([0, 100])
.range([h, 0]);
}
return true;
}));
// Add grey background lines for context.
background = svg.append("svg:g")
.attr("class", "background")
.selectAll("path")
.data(data)
.enter().append("svg:path")
.attr("d", path);
// Add blue foreground lines for focus.
foreground = svg.append("svg:g")
.attr("class", "foreground")
.selectAll("path")
.data(data)
.enter().append("svg:path")
.attr("d", path);
// Add a group element for each dimension.
var g = svg.selectAll(".dimension")
.data(dimensions)
.enter().append("svg:g")
.attr("class", "dimension")
.attr("transform", function (d) {
return "translate(" + x(d) + ")";
})
.call(d3.behavior.drag()
.on("dragstart", function (d) {
dragging[d] = this.__origin__ = x(d);
background.attr("visibility", "hidden");
})
.on("drag", function (d) {
dragging[d] = Math.min(w, Math.max(0, this.__origin__ += d3.event.dx));
foreground.attr("d", path);
dimensions.sort(function (a, b) {
return position(a) - position(b);
});
x.domain(dimensions);
g.attr("transform", function (d) {
return "translate(" + position(d) + ")";
});
})
.on("dragend", function (d) {
delete this.__origin__;
delete dragging[d];
transition(d3.select(this)).attr("transform", "translate(" + x(d) + ")");
transition(foreground)
.attr("d", path);
background.attr("d", path)
.transition()
.delay(500)
.duration(0)
.attr("visibility", null);
}));
// Add an axis and title.
g.append("svg:g")
.attr("class", "axis")
.each(function (d) {
d3.select(this).call(axis.scale(y[d]));
})
.append("svg:text")
.attr("text-anchor", "middle")
.attr("y", -9)
.text(String);
// Add and store a brush for each axis.
g.append("svg:g")
.attr("class", "brush")
.each(function (d) {
d3.select(this).call(y[d].brush = d3.svg.brush().y(y[d]).on("brush", brush));
})
.selectAll("rect")
.attr("x", -8)
.attr("width", 16);
});
function position(d) {
var v = dragging[d];
return v === null ? x(d) : v;
}
function transition(g) {
return g.transition().duration(500);
}
// Returns the path for a given data point.
function path(d) {
return line(dimensions.map(function (p) {
return [position(p), y[p](d[p])];
}));
}
// Handles a brush event, toggling the display of foreground lines.
function brush() {
var actives = dimensions.filter(function (p) {
return !y[p].brush.empty();
}),
extents = actives.map(function (p) {
return y[p].brush.extent();
});
foreground.style("display", function (d) {
return actives.every(function (p, i) {
return extents[i][0] <= d[p] && d[p] <= extents[i][1];
}) ? null : "none";
});
}
This is a chunk of my data:
path,Ktype,label,CGX,CGY,C_1,C_2,C_3,C_4,total1,total2,totalI3,total4,feature1,feature2,feature3,feature4,feature5,A,B,C,D,feature6,feature7,
.\Mydata\Case1,k1,1,42,33,0,57.44534,0,52597,71,16,10,276,74,67,69,33,16,1,0,0,1,9.60E-05,3136.698,
.\Mydata\Case2,k1,3,163,29,0,43.28862,0,49050,71,16,10,248,21,89,8,56,21,1,0,0,1,0.00010854,2676.418,
.\Mydata\Case3,k1,2,774,19,0,45.26291,0,53455,71,16,10,212,35,19,79,45,94,1,1,0,0,9.54E-05,3221.289,
.\Mydata\Case4,k1,1,1116,25,0,80.76469,0,57542,71,16,10,284,73,34,17,48,44,0,1,1,0,0.000140592,2143.42,
.\Mydata\Case5,k1,2,1364,59,1,52.96776,0,49670,71,16,10,228,39,26,55,41,71,0,1,1,0,0.00012014,2439.636,
.\Mydata\Case6,k1,3,1364,59,1,52.96776,0,49670,71,16,10,228,27,38,55,52,71,0,1,1,0,0.00012014,2439.636,
.\Mydata\Case7,k1,1,1364,59,1,52.96776,0,49670,71,16,10,228,89,33,5,17,37,0,1,1,0,0.00012014,2439.636,
.\Mydata\Case8,k1,1,1364,59,1,52.96776,0,49670,71,16,10,228,12,22,10,7,12,0,1,1,0,0.00012014,2439.636
Also, you can find my code here: http://jsfiddle.net/SaraJS/ubBwY/10/
(Also, "test.csv" is here; I could not link it to my code.)
I wasn't able to get your example to work, but I can show you what to do.
First you need to create a color scale, which is an ordinal scale. Then you can set the domain to be the array of values of your input (in your case 1, 2, and 3), and the range should be the colors that correspond to those inputs. For example:
var color = d3.scale.ordinal()
.domain([1,2,3])
.range(['red','green','blue']);
Then when you create your path
element, you can make the stroke color a function of the label data, using the scale:
foreground = svg.append('svg:g')
.attr('class', 'foreground')
.selectAll('path')
.data(data)
.enter().append('svg:path')
.attr('d', path)
.attr('stroke', function(d) { return color(d.label); });
Then just make sure you remove the stroke styling for the foreground from your css so it doesn't override the value your scale provided.
Here's an example that uses a subset of the cars data from this example.