D3 stacked area chart tsv to csv conversion problems - javascript

I am trying to convert this example from tsv to csv.
Currently this is what I have: https://jsfiddle.net/asb1926/sc5wdkLe/
The error I keep getting is this (on the jsfiddle it is line 46):
d3.v4.min.js:7 Uncaught TypeError: Cannot read property 'length' of undefined
at t (d3.v4.min.js:7)
at SVGPathElement.<anonymous> (line:61)
at SVGPathElement.<anonymous> (d3.v4.min.js:2)
at _t._l [as each] (d3.v4.min.js:4)
at _t.yl [as attr] (d3.v4.min.js:4)
at line:59
at Object.<anonymous> (d3.v4.min.js:7)
at _.call (d3.v4.min.js:4)
at XMLHttpRequest.e (d3.v4.min.js:7)
​The csv file I am currently using is this:
date,Detractors,Promoters,Passives
04/23/12,37,12,46
04/24/12,32,19,42
04/25/12,45,16,44
04/26/12,24,52,64

Your date strings have a different format. This is Bostock's dates:
"2015 Jun 15"
This is yours:
"04/23/12"
Therefore, you need a different parser:
var parseDate = d3.timeParse("%m/%d/%Y");
Besides that, your path d attribute is wrong. It should be simply:
.attr("d", area);
Here is your code with that changes:
var svg = d3.select("svg"),
margin = {
top: 20,
right: 20,
bottom: 30,
left: 50
},
width = svg.attr("width") - margin.left - margin.right,
height = svg.attr("height") - margin.top - margin.bottom;
var parseDate = d3.timeParse("%m/%d/%Y");
var x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
z = d3.scaleOrdinal(d3.schemeCategory10);
var stack = d3.stack();
var area = d3.area()
.x(function(d, i) {
return x(d.data.date);
})
.y0(function(d) {
return y(d[0]);
})
.y1(function(d) {
return y(d[1]);
});
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var data = d3.csvParse(d3.select("#csv").text(), type)
var keys = data.columns.slice(1);
x.domain(d3.extent(data, function(d) {
return d.date;
}));
z.domain(keys);
stack.keys(keys);
var layer = g.selectAll(".layer")
.data(stack(data))
.enter().append("g")
.attr("class", "layer");
layer.append("path")
.attr("class", "area")
.style("fill", function(d) {
return z(d.key);
})
.attr("d", area);
layer.filter(function(d) {
return d[d.length - 1][1] - d[d.length - 1][0] > 0.01;
})
.append("text")
.attr("x", width - 6)
.attr("y", function(d) {
return y((d[d.length - 1][0] + d[d.length - 1][1]) / 2);
})
.attr("dy", ".35em")
.style("font", "10px sans-serif")
.style("text-anchor", "end")
.text(function(d) {
return d.key;
});
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).ticks(10, "%"));
function type(d, i, columns) {
d.date = parseDate(d.date);
for (var i = 1, n = columns.length; i < n; ++i) d[columns[i]] = d[columns[i]] / 100;
return d;
}
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg width="500" height="300"></svg>
<pre id="csv">date,Detractors,Promoters,Passives
04/23/12,37,12,46
04/24/12,32,19,42
04/25/12,45,16,44
04/26/12,24,52,64</pre>
PS: I'm using a <pre> element to store the CSV, because I cannot use a real CSV in the Stack snippet.

Related

D3.js path goes in different directions in V3 vs V4

I'm attempting to make the same multi-line graph in D3 V3 and V4, but they behave differently for reasons I don't understand. What can I change in my V4 code that will make the paths connect in the correct order (according to the x axis instead of the y axis)?
Here's what V3 gives, taken from the jsfiddle I made for it:
...But here's V4:
Jsfiddle doesn't support V4 yet, so here's my code:
var margin = {top: 20, right: 40, bottom: 100, left: 100},
width = 500 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var x = d3.scaleLinear().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var xAxis = d3.axisBottom(x);
var yAxis = d3.axisLeft(y);
var line = d3.line()
.x(function(d) { return x(d.depth); })
.y(function(d) { return y(d.carat); });
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 + ")");
d3.csv("diamonds.csv", function(error, data) {
data.forEach(function(d) {
d.carat = +d.carat;
d.depth = +d.depth;
//d.cut = +d.cut;
})
data.sort(function(a,b) { return a.x - b.x; });
x.domain(d3.extent(data, function(d) { return d.depth; })).nice();
y.domain(d3.extent(data, function(d) { return d.carat; })).nice();
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("y", 6)
.attr("x", 5)
.attr("dy", ".35em")
.attr("transform", "rotate(45)")
.style("text-anchor", "start")
var dataNest = d3.nest()
.key(function(d) {return d.cut;})
.entries(data);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Price");
var color = d3.scaleOrdinal(d3.schemeCategory10);
dataNest.forEach(function(d) {
svg.append("path")
.attr("class", "line")
.style("stroke", function() { // Add the colours dynamically
return d.color = color(d.key); })
.attr("d", line(d.values));
});
});
If you look at your code using D3 v3.x, you did this after loading the data:
data.forEach(function(d) {
d.x = +d.depth;
d.carat = +d.carat;
})
And using that property x for sorting:
data.sort(function(a,b) { return a.x - b.x; });
However, in your v4.x version, you did:
data.forEach(function(d) {
d.depth = +d.depth;
d.carat = +d.carat;
})
And used an nonexistent x for sorting (the problem with sorting alone was making the lines different from v3.x).
Solution: use depth for sorting:
data.sort(function(a,b) { return a.depth - b.depth; });
Here is your code using v4.x version:
var margin = {
top: 20,
right: 40,
bottom: 100,
left: 100
},
width = 500 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var x = d3.scaleLinear().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
var xAxis = d3.axisBottom(x);
var yAxis = d3.axisLeft(y);
var line = d3.line()
.x(function(d) {
return x(d.depth);
})
.y(function(d) {
return y(d.carat);
});
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 data = d3.csvParse(d3.select("pre#data").text());
data.forEach(function(d) {
d.carat = +d.carat;
d.depth = +d.depth;
//d.cut = +d.cut;
})
data.sort(function(a, b) {
return a.depth - b.depth;
});
x.domain(d3.extent(data, function(d) {
return d.depth;
})).nice();
y.domain(d3.extent(data, function(d) {
return d.carat;
})).nice();
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("y", 6)
.attr("x", 5)
.attr("dy", ".35em")
.attr("transform", "rotate(45)")
.style("text-anchor", "start")
var dataNest = d3.nest()
.key(function(d) {
return d.cut;
})
.entries(data);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Price");
var color = d3.scaleOrdinal(d3.schemeCategory10);
dataNest.forEach(function(d) {
svg.append("path")
.attr("class", "line")
.style("stroke", function() { // Add the colours dynamically
return d.color = color(d.key);
})
.attr("d", line(d.values));
});
pre {
display:none;
}
path
{
fill: none;
stroke: #000;
}
.line {
fill: none;
// stroke: green;
// stroke-width: 3.5px;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<pre id="data">
carat,cut,color,clarity,depth,table,price,x,y,z
0.41,Ideal,G,VS1,60.8,56,899,4.79,4.82,2.92
0.3,Ideal,F,VS1,62.1,55,612,4.31,4.35,2.69
1.25,Ideal,H,SI1,62.2,57,6661,6.86,6.9,4.28
0.41,Ideal,G,VS2,61.4,55,1061,4.8,4.75,2.93
0.53,Premium,E,VVS2,62.4,56,2331,5.19,5.17,3.23
1.14,Very Good,G,VS2,63.2,56,6435,6.67,6.63,4.2
0.51,Premium,G,SI1,62,59,1053,5.12,5.1,3.17
1.51,Good,H,VVS2,63.1,59,11826,7.26,7.28,4.59
1.31,Ideal,J,SI1,62.5,56,6337,6.95,7.04,4.37
0.33,Very Good,I,VVS1,61.7,61,608,4.43,4.45,2.74
0.42,Ideal,F,VS1,62.3,55,1103,4.79,4.77,2.98
1.01,Good,E,VS2,60.8,63,6250,6.44,6.46,3.92
1,Premium,F,SI1,62.7,59,5292,6.4,6.36,4
0.51,Ideal,G,VVS1,61.9,53,1919,5.14,5.2,3.2
0.34,Ideal,H,SI1,61.5,55,647,4.53,4.55,2.79
0.23,Premium,F,VVS2,61.3,59,445,3.94,3.99,2.43
0.3,Ideal,F,VS2,62.9,57,776,4.29,4.27,2.69
1.14,Premium,F,SI1,60.4,58,6320,6.82,6.79,4.11
0.33,Ideal,J,VVS1,62.1,54,509,4.45,4.47,2.77
0.41,Premium,H,SI1,60.9,60,683,4.79,4.83,2.93
2.01,Premium,J,SI2,62.8,58,12407,8.09,8,5.05
2.01,Very Good,I,SI1,60.3,59,15126,8.14,8.21,4.93
0.4,Very Good,D,VS2,62.8,58,993,4.66,4.71,2.94
1.09,Premium,D,SI1,61.6,58,5799,6.61,6.57,4.06
0.3,Ideal,F,VS1,61.5,55,612,4.31,4.34,2.66
0.77,Very Good,H,SI2,63.6,58,2129,5.77,5.81,3.68
0.38,Very Good,F,VS1,62.7,57,883,4.71,4.64,2.93
0.54,Premium,E,VS1,60.3,58,1939,5.26,5.32,3.19
0.93,Premium,F,SI1,58.8,60,4010,6.49,6.37,3.78
0.32,Ideal,H,VS1,61.1,56,561,4.44,4.46,2.72
0.78,Premium,F,SI2,62.8,56,2200,5.9,5.86,3.69
0.4,Ideal,E,VS1,61.2,55,1005,4.79,4.76,2.92
0.41,Ideal,D,VS2,62.4,55,1076,4.79,4.76,2.98
0.73,Very Good,E,SI1,61.6,59,2760,5.77,5.78,3.56
2.52,Very Good,G,SI2,63.2,58,17689,8.65,8.61,5.45
1.06,Ideal,D,VVS2,62,56,12053,6.53,6.57,4.06
0.8,Very Good,D,IF,63.3,57,6834,5.85,5.87,3.71
1.5,Premium,H,VS2,62.2,58,10291,7.27,7.36,4.55
2.17,Good,H,SI2,58.9,62,16036,8.48,8.52,5.01
1.58,Ideal,G,SI1,62.2,55,11927,7.44,7.5,4.65
2.03,Premium,H,VS2,62.1,56,18139,8.2,8.12,5.07
0.58,Very Good,D,SI2,62.9,56,1438,5.31,5.35,3.35
0.72,Very Good,D,VS2,62.1,59,3016,5.7,5.73,3.55
0.38,Ideal,D,VVS2,61.5,57,1200,4.63,4.67,2.86
0.5,Premium,E,VS2,61.3,60,1624,5.07,5.11,3.12
0.31,Ideal,F,VS2,61.1,56,640,4.35,4.39,2.67
1.41,Premium,D,SI2,61.1,56,6988,7.19,7.15,4.38
0.7,Good,I,VS1,63.2,55,2274,5.58,5.63,3.54
1.22,Ideal,F,SI2,62,57,4852,6.88,6.83,4.25
1.58,Ideal,H,VS2,61.4,56,12334,7.5,7.56,4.62
1.2,Ideal,G,VS1,62,55,9625,6.81,6.87,4.24
1.03,Premium,H,I1,61.1,60,3172,6.46,6.51,3.96
0.77,Very Good,H,VS1,62.8,58,2961,5.75,5.78,3.62
1.04,Ideal,I,VS2,61.5,57,5105,6.49,6.52,4
1,Good,H,SI1,63.7,60,4788,6.33,6.3,4.02
0.82,Very Good,G,IF,61.9,57,4844,5.96,6,3.7
0.71,Ideal,D,VS1,60.9,57,3518,5.74,5.76,3.5
1.21,Ideal,I,SI2,64.6,56,4879,6.67,6.62,4.29
0.4,Very Good,E,SI1,61.7,60,687,4.68,4.72,2.9
1.11,Premium,H,SI1,61.1,60,5433,6.68,6.62,4.06
1.5,Ideal,F,VS2,60.4,57,14071,7.41,7.43,4.48
1.48,Very Good,H,SI1,62.5,59,8815,7.16,7.23,4.5
0.28,Ideal,F,VVS2,61.5,57,787,4.19,4.24,2.59
0.64,Very Good,E,VS2,63.4,54,2114,5.52,5.49,3.49
1.68,Ideal,I,VS2,62.1,57,10800,7.6,7.54,4.7
0.93,Premium,G,SI2,61.7,60,3802,6.25,6.2,3.84
0.34,Very Good,E,SI1,62.9,56,596,4.45,4.48,2.81
1.57,Premium,G,VS1,59.9,56,14180,7.6,7.55,4.54
1.16,Premium,H,SI2,61.8,58,4872,6.81,6.75,4.19
0.3,Ideal,E,VVS2,61.4,57,1013,4.34,4.32,2.66
1.06,Very Good,F,SI1,63.4,58,5520,6.51,6.42,4.1
1.14,Ideal,H,SI1,61.6,56,7079,6.72,6.74,4.14
1,Premium,J,SI1,58.7,58,3920,6.55,6.51,3.83
2.01,Very Good,F,SI2,63.3,59,11925,7.98,7.89,5.02
1.37,Premium,G,VS1,58.3,60,10412,7.35,7.3,4.27
0.91,Premium,E,SI2,61.6,60,3846,6.14,6.1,3.77
1,Premium,G,VS2,63,58,6048,6.4,6.33,4.01
0.4,Good,G,SI1,63.4,58,655,4.66,4.71,2.97
1.39,Very Good,G,SI2,61.5,62,6628,7.09,7.16,4.38
0.31,Ideal,G,IF,62.7,57,924,4.31,4.34,2.71
1.5,Premium,H,VS2,62.4,59,11092,7.29,7.32,4.56
0.99,Very Good,F,SI1,62.5,58,5112,6.36,6.38,3.98
1.5,Very Good,I,VVS2,64,54,9618,7.19,7.27,4.63
1.04,Very Good,E,VVS2,62.4,58,8748,6.46,6.4,4.01
1.01,Premium,H,SI1,61.8,59,5204,6.38,6.33,3.93
0.71,Fair,D,SI1,55.5,62,2086,6,5.97,3.32
0.26,Ideal,G,VS1,62.1,55,478,4.09,4.12,2.55
0.92,Premium,E,SI1,61.7,57,4637,6.32,6.2,3.86
0.32,Ideal,E,VS2,61.8,54,768,4.43,4.4,2.73
0.54,Ideal,H,IF,61.5,54,1981,5.27,5.3,3.25
0.4,Ideal,G,IF,61.2,56,1199,4.74,4.77,2.91
1.28,Very Good,G,VVS2,59.5,56,11478,7.12,7.16,4.25
0.42,Premium,G,VS2,60.6,59,1087,4.85,4.78,2.92
1.04,Premium,H,VS2,60.4,59,5777,6.66,6.51,3.98
0.91,Premium,G,SI1,61.8,60,4045,6.18,6.21,3.83
0.33,Very Good,H,VS2,58.8,62,486,4.49,4.53,2.65
0.31,Ideal,E,VS1,61.3,54,664,4.37,4.4,2.69
0.61,Very Good,D,VS1,62.4,57,2096,5.44,5.46,3.4
0.3,Ideal,H,VVS2,61.6,55,605,4.3,4.34,2.66
1.57,Premium,J,VS1,61.3,59,8595,7.44,7.47,4.57
0.72,Very Good,J,VS1,62.3,57,2136,5.73,5.77,3.58
1.11,Premium,F,SI2,62.2,57,5284,6.67,6.61,4.13
0.4,Premium,D,SI2,61.7,58,855,4.74,4.69,2.91
0.7,Good,F,VVS1,63.3,56,3310,5.64,5.7,3.59
1,Premium,D,SI2,59.4,60,4626,6.56,6.48,3.87
0.61,Ideal,E,VVS2,62,54,3011,5.43,5.47,3.38
1,Premium,F,VS2,62.8,59,6328,6.35,6.32,3.98
1.05,Ideal,F,SI2,60.9,56,4591,6.56,6.64,4.02
1.01,Premium,I,SI1,61.6,58,3944,6.45,6.51,3.99
0.51,Ideal,F,VS2,63.2,57,1687,5.08,5.05,3.2
1.2,Premium,H,SI2,62.4,61,5040,6.81,6.78,4.24
1.52,Ideal,J,VS1,62.3,58,8608,7.32,7.35,4.57
0.51,Premium,F,VVS2,61.9,56,2310,5.17,5.13,3.19
0.5,Very Good,H,IF,61.4,61,1923,5.14,5.03,3.12
1.01,Premium,G,SI1,63,60,4118,6.34,6.3,3.98
0.8,Very Good,F,VS1,62.6,57,3720,5.9,5.98,3.72
2.01,Very Good,I,SI1,62.8,60,14811,7.99,8.04,5.03
1,Premium,E,SI1,61.6,59,5600,6.41,6.38,3.94
1,Good,J,VS1,58.1,64,3920,6.63,6.51,3.82
0.52,Premium,F,VS2,61.4,62,1605,5.19,5.16,3.18
1.3,Very Good,I,VS2,61.8,56,7087,6.98,7.04,4.33
2,Very Good,I,SI1,62.9,59.2,15081,7.95,8.08,5.05
0.31,Very Good,I,VS2,61.6,56,468,4.36,4.39,2.69
1.63,Very Good,I,SI1,62,54,9090,7.6,7.67,4.73
0.3,Premium,H,VVS2,62.1,52,776,4.31,4.29,2.67
1.1,Premium,G,VS2,62.8,58,6387,6.6,6.58,4.14
0.23,Very Good,F,VVS2,61,59,465,3.93,3.97,2.41
1.23,Premium,I,SI2,62.1,59,4773,6.83,6.79,4.23
1.02,Good,G,VS2,63.6,57,5816,6.38,6.41,4.07
0.71,Premium,F,VS1,59.2,58,2839,5.87,5.82,3.46
1.69,Ideal,H,I1,62,56,6757,7.66,7.61,4.73
1.6,Ideal,G,VS2,61.9,56,15000,7.53,7.47,4.64
0.32,Ideal,H,IF,61.9,54.2,783,4.38,4.42,2.72
0.73,Very Good,G,SI2,62.2,58,2057,5.71,5.77,3.57
0.32,Ideal,D,VS2,62.7,54,758,4.36,4.38,2.74
0.7,Ideal,E,VS2,61.1,59,3201,5.67,5.73,3.48
0.3,Ideal,H,VS1,62.1,54,526,4.32,4.35,2.69
0.9,Good,I,VS2,63.8,55,3303,6.07,6.16,3.9
0.52,Premium,H,SI2,60.9,61,975,5.15,5.1,3.12
0.97,Premium,F,SI1,62.7,59,4561,6.28,6.31,3.95
0.32,Very Good,H,SI1,62.6,55,461,4.37,4.38,2.74
0.54,Ideal,F,SI1,61.2,56,1307,5.23,5.29,3.22
1.21,Good,F,VS2,63.7,58,7911,6.67,6.71,4.26
1.51,Very Good,I,SI1,63.1,56,7891,7.28,7.33,4.61
1.01,Premium,F,VS2,58.9,58,6271,6.59,6.51,3.86
1.57,Very Good,J,VS2,62.6,59,7832,7.39,7.43,4.64
0.73,Premium,I,VS1,60.3,58,2371,5.83,5.87,3.53
1.2,Ideal,I,SI1,62.5,57,5107,6.77,6.71,4.21
3.04,Premium,I,SI2,59.3,60,18559,9.51,9.46,5.62
0.31,Very Good,G,VVS1,63.1,56,1046,4.35,4.33,2.74
0.5,Premium,E,I1,60.7,61,840,5.14,5.05,3.09
0.38,Ideal,I,VS1,62.4,54.4,703,4.62,4.66,2.9
1.12,Premium,G,VS2,60.7,53,6774,6.81,6.7,4.1
1.33,Premium,F,SI2,60.7,62,5288,7.12,7.07,4.31
1.11,Ideal,J,VS1,61.7,57,4854,6.67,6.72,4.13
0.71,Ideal,G,SI1,62.4,56,2386,5.74,5.71,3.57
1.03,Ideal,G,VS1,62.1,57,6558,6.44,6.47,4.01
0.32,Very Good,G,VVS1,61.4,55,772,4.41,4.45,2.72
1.55,Premium,D,VS2,61.5,58,16137,7.51,7.48,4.61
0.72,Premium,F,VS2,60.8,58,2530,5.78,5.74,3.5
0.31,Good,F,VS2,63.4,56,625,4.29,4.32,2.73
0.42,Ideal,G,IF,62,57,1310,4.82,4.8,2.98
2.1,Premium,H,SI2,60.4,59,16479,8.28,8.33,5.02
0.66,Ideal,H,VS2,61.4,56,2178,5.62,5.65,3.46
0.48,Premium,F,SI1,60.6,62,1110,5.06,5,3.05
0.91,Very Good,D,SI1,63,59,4429,6.11,6.15,3.86
0.5,Ideal,E,SI2,62.5,57,1154,5.04,5.07,3.16
0.57,Ideal,I,VS1,62.2,55,1448,5.28,5.33,3.3
1.09,Premium,F,SI1,60.9,59,5384,6.64,6.59,4.03
1,Premium,H,SI1,62.3,60,4788,6.38,6.34,3.96
0.4,Very Good,E,VS2,63,58,791,4.7,4.73,2.97
1.2,Ideal,I,SI1,60.1,56,5578,6.9,6.84,4.13
0.71,Premium,I,VS2,59.3,59,2300,5.89,5.81,3.47
0.34,Ideal,D,VS2,62,55,1033,4.48,4.45,2.77
1.25,Good,J,SI1,63.6,57,5110,6.86,6.81,4.35
0.41,Ideal,D,SI1,61.7,54,1015,4.79,4.78,2.95
0.51,Fair,D,SI2,66.5,58,1109,4.95,4.89,3.27
0.56,Ideal,E,SI1,62.7,57,1698,5.27,5.23,3.29
1.04,Ideal,G,VS1,61.5,57,7457,6.5,6.54,4.01
0.3,Ideal,I,SI1,61.9,57,422,4.29,4.31,2.66
0.5,Premium,F,VS2,61.7,60,1323,5.06,5.02,3.11
0.28,Very Good,G,VVS2,62.3,56,522,4.16,4.19,2.6
0.37,Very Good,E,VS1,62,56,925,4.59,4.63,2.86
0.8,Premium,F,SI2,58.5,62,2371,6.08,6.05,3.55
0.81,Very Good,F,SI2,62.7,58,2942,5.92,5.95,3.72
0.51,Ideal,E,VVS2,62.8,56,2211,5.13,5.15,3.23
0.98,Ideal,G,SI1,62.3,56,4665,6.37,6.34,3.96
1.51,Good,H,VS2,63.6,61,8904,7.08,7.03,4.49
0.5,Premium,D,SI1,60.3,58,1433,5.12,5.1,3.08
0.43,Ideal,F,VVS2,62.2,55,1250,4.85,4.83,3.01
0.7,Ideal,F,SI1,61.1,57,2516,5.75,5.71,3.5
0.3,Premium,E,SI1,61.8,60,675,4.28,4.23,2.63
0.7,Very Good,F,VS2,62.9,56,2400,5.66,5.73,3.58
0.92,Very Good,D,VS1,61.9,58,7544,6.19,6.24,3.85
2.57,Premium,J,SI1,63,58,18485,8.77,8.65,5.49
2.25,Ideal,I,SI2,60.7,56,11104,8.54,8.5,5.17
0.51,Ideal,G,VVS2,61.5,57,1875,5.13,5.18,3.17
1.05,Ideal,H,SI2,61.9,56,4504,6.49,6.56,4.04
0.3,Ideal,E,VS1,62.5,56,694,4.27,4.31,2.68
1.01,Premium,J,VS2,62.4,60,3296,6.45,6.35,3.99
</pre>

X axis not displaying on Multi Series Line Chart using d3.js

I am implementing a multi series line chart in d3.js following the example on this block: http://bl.ocks.org/mbostock/3884955. However, the X axis is not displaying. The X axis should display the dates. Here is my code:
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.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 parseTime = d3.timeParse("%Y%m%d");
var x = d3.scaleBand().rangeRound([0, width]),
// xAxis = d3.svg.axis().scale(x).orient("bottom"),
y = d3.scaleLinear().range([height, 0]),
z = d3.scaleOrdinal(d3.schemeCategory10);
var line = d3.line()
.curve(d3.curveBasis)
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.price); });
d3.tsv("data.tsv", type, function(error, data) {
if (error) throw error;
var products = data.columns.slice(1).map(function(id) {
return {
id: id,
values: data.map(function(d) {
return {date: d.date, price: d[id]};
})
};
});
x.domain(data.map( function(d) { return d.date; }));
y.domain([
d3.min(products, function(c) { return d3.min(c.values, function(d) { return d.price; }); }),
d3.max(products, function(c) { return d3.max(c.values, function(d) { return d.price; }); })
]);
z.domain(products.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("Price $");
var product = g.selectAll(".product")
.data(products)
.enter().append("g")
.attr("class", "product");
product.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return z(d.id); });
product.append("text")
.datum(function(d) { return {id: d.id, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.price) + ")"; })
.attr("x", 3)
.attr("dy", "0.35em")
.style("font", "10px sans-serif")
.text(function(d) { return d.id; });
});
function type(d, _, columns) {
d.date = parseTime(d.date);
for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c];
return d;
}
Here is the resultant chart from my code:- http://bizvizmap.com/timeseries.html
You probably have some problem in your data, because this plunker has exactly your code, with some bogus data I created:
date,foo,bar,baz
20160101,11,23,45
20160102,21,22,35
20160103,44,76,54
20160104,31,23,45
20160105,41,63,15
20160106,12,22,25
Here is the plunker: https://plnkr.co/edit/xZY02zVTEh6o9RwNGJBw?p=preview
The ticks on the x axis are a mess because you're using the full JS date in an ordinal scale. Because of that, it makes more sense using a time scale, as in this other plunker: https://plnkr.co/edit/n5u8N9aK8YELtTCHexgR?p=preview

How can I convert this D3 multi-series line chart x-axis to use sequential numbers instead of date values?

I am trying convert this chart I made, disregard the styles, using Highcharts, to this D3 multi-line chart.
This is the code for the d3 viz.
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.axis--x path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.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 parseTime = d3.timeParse("%Y%m%d");
var x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
z = d3.scaleOrdinal(d3.schemeCategory10);
var line = d3.line()
.curve(d3.curveBasis)
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.temperature); });
d3.tsv("data.tsv", type, function(error, data) {
if (error) throw error;
var cities = data.columns.slice(1).map(function(id) {
return {
id: id,
values: data.map(function(d) {
return {date: d.date, temperature: d[id]};
})
};
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(cities, function(c) { return d3.min(c.values, function(d) { return d.temperature; }); }),
d3.max(cities, function(c) { return d3.max(c.values, function(d) { return d.temperature; }); })
]);
z.domain(cities.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("Temperature, ºF");
var city = g.selectAll(".city")
.data(cities)
.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); });
city.append("text")
.datum(function(d) { return {id: d.id, value: d.values[d.values.length - 1]}; })
.attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")"; })
.attr("x", 3)
.attr("dy", "0.35em")
.style("font", "10px sans-serif")
.text(function(d) { return d.id; });
});
function type(d, _, columns) {
d.date = parseTime(d.date);
for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c];
return d;
}
</script>
I would like to keep the data in a tsv and just convert the x-axis from using dates to using the raw numbers seen in the Highchart series. So instead of city, date, and temperature it would be batter, game number, and slugging percentage. I would also like to make it so that the lines end, like in the Highchart example, once there is no corresponding value, and not just have the line dip down to 0. It would also be nice if I could keep the hover effect from the Highchart example.
Unfortunately, I have little idea in how to achieve this. I know that I have to use a different function than the parseTime function currently in the script but that's about as far as I've gotten.
Change your scale to:
var x = d3.scaleLinear().range([0, width])
And don't parse to a date:
function type(d, _, columns) {
d.date = +d.date;
for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c];
return d;
}

D3 - Having trouble updating stacked bar chart

I have a real simple horizontally stacked bar chart with 3 bars that are all on the same scale (i.e. each 0 to 100 with the stacked bars consisting of numbers that make up 100).
When trying to update my data nothing appears to happen. I've not been able to figure out how to update the data and it's been driving me crazy.
Relevant Code:
<body>
<div id='updateTest'>
Update Data
</div>
<div id='chart'></div>
<script>
$( document ).ready(function() {
$( "#updateTest" ).click(function() {
updateData();
console.log(allData[count]);
});
});
var institution;
// Set up the SVG data
var allData = ["data.csv","data2.csv","data3.csv"];
var count = 0;
var margin = {top: 20, right: 20, bottom: 145, left: 115},
width = 960 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var y = d3.scale.ordinal()
.rangeRoundBands([height, 0], .1);
var x = d3.scale.linear()
.rangeRound([0, width]);
var color = d3.scale.ordinal()
.range(["#98abc5", "#8a89a6", "#7b6888"]);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(d3.format(".2s"));
var svg = d3.select("#chart").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 + ")");
// Bind initial shown data to the SVG
d3.csv(allData[count], function(error, data) {
if (error) throw error;
color.domain(d3.keys(data[0]).filter(function(key) {
return key !== "Institution";
}));
data.forEach(function(d) {
var y0 = 0;
d.ages = color.domain().map(function(name) {
return {name: name, y0: y0, y1: y0 += +d[name]};
});
d.total = d.ages[d.ages.length - 1].y1;
});
data.sort(function(a, b) { return b.total - a.total; });
y.domain(data.map(function(d) { return d.Institution; }));
x.domain([0, d3.max(data, function(d) { return d.total; })]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("x", -32)
.attr("y", -112)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Institution");
institution = svg.selectAll(".institution")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) {
return "translate(0," + y(d.Institution) + ")"; });
institution.selectAll("rect")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("height", y.rangeBand())
.attr("x", function(d) { return x(d.y0); })
.attr("width", function(d) { return x(d.y1) - x(d.y0); })
.style("fill", function(d) { return color(d.name); });
var legend = svg.selectAll(".legend")
.data(color.domain().slice().reverse())
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) {
return "translate(0," + i * 28 + ")"; });
legend.append("rect")
.attr("x", -20)
.attr("y", 190)
.attr("width", 25)
.attr("height", 25)
.style("fill", color);
legend.append("text")
.attr("x", 10)
.attr("y", 203)
.attr("dy", ".35em")
.style("text-anchor", "left")
.text(function(d) { return d; });
});
/* updateData()
* Rebinds the SVG to a new dataset
*/
function updateData() {
// Iterate through the data
var newData;
if (count === allData.length - 1)
count = 0;
else
count++;
newData = allData[count];
// Get the data again
d3.csv(allData[count], function(error, data) {
data.forEach(function(d) {
d.close = +d.close;
});
// Make the changes
institution.selectAll("rect")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("height", y.rangeBand())
.attr("x", function(d) { return x(d.y0); })
.attr("width", function(d) { return x(d.y1) - x(d.y0); })
.style("fill", function(d) { return color(d.name); });
});
}
</script>
</body>
My CSV files:
data.csv
Institution,CurrentlyOweBehind,CurrentlyOweNotBehind,Paid
For-profit,15,35,50
Nonprofit,11,48,41
Public,26,16,58
data2.csv
Institution,CurrentlyOweBehind,CurrentlyOweNotBehind,Paid
For-profit,23,33,44
Nonprofit,28,12,60
Public,12,8,80
data3.csv
Institution,CurrentlyOweBehind,CurrentlyOweNotBehind,Paid
For-profit,61,22,17
Nonprofit,7,43,50
Public,41,19,40
The main bit is in the updateData() function. I am able to create the chart and display data but I do not understand transitioning the data...
I'm getting no errors in the console and it's properly cycling the data.
The problems is with d.ages in the update function. You basically need the same setup that you have for the initial plot. So I added the following in the d3.csv block of your update function:
data.forEach(function(d) {
var y0 = 0;
d.ages = color.domain().map(function(name) {
return {name: name, y0: y0, y1: y0 += +d[name]};
});
d.total = d.ages[d.ages.length - 1].y1;
});
institution = svg.selectAll(".institution")
.data(data);
The class name for institution was set to g for some reason, and I changed that to institution. Also, you do not need .enter().append("rect") at this point. Finally I added a transition and duration.
I have created a plunk, with all your csv files included: http://plnkr.co/edit/CYFNWZKuiLo9gFps49e9?p=preview
Hope this helps.

Error parsing with multiline graph in D3

I'm trying to create a multiline graph using D3, and I keep running across the same error
Error: Problem parsing d="MNaN,450LNaN,0LNaN,450LNaN,450LNaN,0LNaN,0"
Which seems to occur when I try to graph my line:
city.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name); });
I'm trying to graph a single line at the moment with the following data set:
{"name":"application_active_users","values":[{"value":0,"end_time":"2013-06-14T11:00:00.000Z"},{"value":1,"end_time":"2013-06-15T11:00:00.000Z"},{"value":0,"end_time":"2013-06-16T11:00:00.000Z"},{"value":0,"end_time":"2013-06-17T11:00:00.000Z"},{"value":1,"end_time":"2013-06-18T11:00:00.000Z"},{"value":1,"end_time":"2013-06-19T11:00:00.000Z"}]}
I'm assuming something is wrong with my datasource. Does anyone see an immediate issue with how my datasource is set up?
Here is a portion of the D3 code. The entire code is here http://jsfiddle.net/hy4Hz/.
var payload;
var storedMetrics = [];
var metricCount = 1;
var graphData = [];
var margin = {
top: 20,
right: 20,
bottom: 30,
left: 50
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
//var parseDate = d3.time.format("%Y-%m-%d").parse;
//var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%SZ").parse;
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S").parse;
var color = d3.scale.category10();
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.x(function (d) {
return x(d.end_time);
})
.y(function (d) {
return y(d.value);
});
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 + ")");
x.domain(d3.extent(
data, function (d) {
return d.end_time;
}));
y.domain([
d3.min(metrics, function (c) {
return d3.min(c.values, function (v) {
return v.value;
});
}),
d3.max(metrics, function (c) {
return d3.max(c.values, function (v) {
return v.value;
});
})]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Temperature (ºF)");
var city = svg.selectAll(".city")
.data(metrics)
.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 color(d.name);
});
city.append("text")
.datum(function (d) {
return {
name: d.name,
value: d.values[d.values.length - 1]
};
})
.attr("transform", function (d) {
return "translate(" + x(d.value.end_time) + "," + y(d.value.value) + ")";
})
.attr("x", 3)
.attr("dy", ".35em")
.text(function (d) {
return d.name;
});
It looks like your x.domain() might not be set up correctly. The first argument to d3.extent should be data.values.

Categories

Resources