I used the code below to make a multiple line graph in d3 with a linear x-axis and it works just fine. Now I want to make the x-axis ordinal, but I have no clue how to do this. Any help would be amazing!
Code:
<!DOCTYPE html>
<html>
<body>
<center><h1>ZNF expression DFC</h1></center>
<meta charset="utf-8">
<style>
.axis--x path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 3.0px;
}
div.tooltip {
position: absolute;
text-align: center;
width: 60px;
height: 18px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
</style>
<svg width="1560" height="1000"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 80, bottom: 30, left: 50},
width = svg.attr("width") - margin.left - margin.right,
height = svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleLinear().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
z = d3.scaleOrdinal(d3.schemeCategory20);
// Define the div for the tooltip
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var line = d3.line()
.x(function(d) { return x(d.Age); })
.y(function(d) { return y(d.expression); });
d3.csv("expression_ZNF_ages.csv", function(error, data) {
if (error) throw error;
var znfs = data.columns.slice(1).map(function(id) {
return {
id: id,
values: data.map(function(d) {
return {Age: d.Age, expression: d[id]};
})
};
});
x.domain([0, data.length]).range([0, width]);
y.domain([0, 40]).range([height,0]);
z.domain(znfs.map(function(c) { return c.id; }));
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.attr("fill", "#000")
.text("expression" );
var city = g.selectAll(".city")
.data(znfs)
.enter().append("g")
.attr("class", "city");
city.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return z(d.id); })
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div .html(d.id)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
});
</script>
</body>
</html>
The data with which I want to work is a csv file and looks like this:
Age, ZNF8, ZNF18, ZNF136, ZNF140 .... ZNF778,
"8pwc", 13.654, 12.643, 10.593, 8,124, .... 9.900,
"9pwc", 4.364, 1.004, 3.576, 0.032, .... 5.512,
"2yrs", 65.345, 53.278, 33.001, 68.844, .... 54.544,
....
Thank you!
In this particular case, you have to use a point scale, which is a type of ordinal scale:
Point scales are a variant of band scales with the bandwidth fixed to zero. Point scales are typically used for scatterplots with an ordinal or categorical dimension.
A point scale will allow you to map a categorical (qualitative) variable to a continuous numeric output.
Thus, your scale should be:
var x = d3.scalePoint().range([0, width])
And its domain should be defined with a map
:
x.domain(data.map(d=>d.Age));
Here is the working code: https://plnkr.co/edit/2nOLP5fEIHbs2U8OQB2y?p=preview