D3 line chart - Error: <path> attribute d: Expected number - javascript

I got this CSV data (just a sample- it is bigger):
value;count
25;1
28;1
29;3
31;2
34;1
36;1
37;2
I could not find any example which shows line chart without Date function so I modified the example to make linear scales but it does not work. I am trying to make line chart with this code but I get Error: attribute d: Expected number
// set the dimensions and margins of the graph
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// set the ranges
var x = d3.scaleLinear().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
// define the line
var valueline = d3.line()
.x(function(d) { return x(d.value); })
.y(function(d) { return y(d.count); });
// append the svg obgect to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
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 + ")");
// Get the data
d3.csv("exp2.csv", function(error, data) {
if (error) throw error;
// format the data
data.forEach(function(d) {
d.value = +d.value;
d.count = +d.count;
});
// Scale the range of the data
x.domain([0, d3.max(data, function(d) { return d.value; })]);
y.domain([0, d3.max(data, function(d) { return d.count; })]);
// Add the valueline path.
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", valueline);
// Add the X Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Add the Y Axis
svg.append("g")
.call(d3.axisLeft(y));
});

As #GerardoFurtado pointed out your data is not csv (ie comma separated) but semi-colon separated. My initial thought was to close this as a duplicate of this question but it looks like the syntax has changed enough in version 4 that I new answer is warranted.
Do this:
// set up a parser
var parser = d3.dsvFormat(';').parse;
// get the data as text
d3.text("exp2.csv", function(error, data) {
if (error) throw error;
// now parse the data
data = parser(data);
// format the data
data.forEach(function(d) {
d.value = +d.value;
d.count = +d.count;
});
...
Here's a full running example.

Related

d3.v5.min.js:2 Error: <path> attribute d: Expected moveto path command ('M' or 'm'), "function a(a){va…"

I am trying to plot a multi-line graph with d3.js but I am getting this error:
Error: attribute d: Expected moveto path command ('M' or 'm'), "function t(t){va…".
I have been stuck at it a while now and tried everything I could think of, to help you in your reflections, Find the code that I use below.
// set the dimensions and margins of the graph
var margin = {top: 10, right: 30, bottom: 30, left: 60},
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
const dateParser = d3.timeFormat("%Y-%m-%d %H:%M:%S");
data.forEach(function(d) {
d.ts = dateParser(new Date(d.ts));
d.value = parseFloat(d.value)
});
// append the svg object to the body of the page
var svg = d3.select("#graph")
.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 + ")");
//Read the data
// group the data: I want to draw one line per group
var sumstat = d3.nest() // nest function allows to group the calculation per level of a factor
.key(function(d) { return d.key;})
.entries(data);
// Add X axis --> it is a date format
var x = d3.scaleLinear()
.domain(d3.extent(data, function(d) { return d.ts; }))
.range([ 0, width ]);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(5));
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data, function(d) { return +d.value; })])
.range([ height, 0 ]);
svg.append("g")
.call(d3.axisLeft(y));
// color palette
var res = sumstat.map(function(d){ return d.key }) // list of group names
var color = d3.scaleOrdinal()
.domain(res).range(['#e41a1c','#377eb8','#4daf4a','#984ea3','#ff7f00','#ffff33','#a65628','#f781bf','#999999'])
// Draw the line
svg.selectAll(".line")
.data(sumstat)
.enter()
.append("path")
.attr("fill", "none")
.attr("stroke", function(d){ return color(d.key) })
.attr("stroke-width", 1.5)
.attr("d", function(d){
return d3.line()
.x(function(d) { return x(d.ts); })
.y(function(d) { return y(d.value); })
})
I cannot figure what I am doing wrong, in case the example I am looking at is this link. I am fairly new to d3 and it is not an easy library to use
When you set the d attribute, you return the line generator itself from the data linking function, but you fail to execute it. Configuring the generator and executing it is a two-step process:
first, contruct and configure the generator (line is a function)
var line = d3.line()
.x(function(d) { return x(d.ts); })
.y(function(d) { return y(d.value); })
then, pass the function to attr(), so it will be executed as line(d)
svg.selectAll(".line")
.data(sumstat)
.enter()
.append("path")
.attr("fill", "none")
.attr("stroke", function(d){ return color(d.key) })
.attr("stroke-width", 1.5)
.attr("d", line)

Add labels to d3 line graph

I am using D3.js to create a simple line graph.
<div>
<h6>Price Over Time</h6>
<div id="priceOverTimeChart"></div>
</div>
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 800 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%d-%b-%y").parse;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(10);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(10);
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
// Adds the svg canvas
var svg = d3.select("#priceOverTimeChart")
.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 + ")");
// Get the data
d3.csv("data.csv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.close; })]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
The data for the line graph uses the following data format:
26-Apr-12,0.048
25-Apr-12,0.048
24-Apr-12,0.048
I would like to add an optional string to each record so it looks like:
26-Apr-12,0.048, "product 1 launch",
25-Apr-12,0.048, "product 2",
24-Apr-12,0.048, "product 3"
26-Apr-12,0.048, null
25-Apr-12,0.048, null
24-Apr-12,0.048, null
The graph would then look something like this with the labels on it:
Graph with optional labels
How can I accomplish this? Thanks in advance!
Appending texts to the corresponding x, y position will do the trick.
Please refer this working JS Fiddle
svg.append("g").selectAll("text")
.data(data)
.enter()
.append("text")
.attr("x", function(d) { return x(d.date) - paddingForText })
.attr("y", function(d) { return y(d.close) + paddingForText })
.attr("fill", "red")
.text(function(d) { return d.notes });

d3 line chart not showing,can not read in date data

Here is my code:
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%d-%m-%y").parse;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(+d.AtTime); })
.y(function(d) { return y(d.Temperature); });
// Adds the svg canvas
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 + ")");
// Get the data
d3.csv("../datasets/test.csv", function(error, data) {
data.forEach(function(d) {
d.AtTime = parseDate(d.AtTime);
d.Temperature = +d.Temperature;
});
console.log(data);
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.AtTime; }));
y.domain([0, d3.max(data, function(d) { return d.Temperature; })]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
And the line chat just can not show...Here is my simple csv dataset:
Category,Temperature,Pressure,AtTime
A,76,400,1-1-2014
B,23,239,2-3-2013
C,38.6,378,2-6-2016
D,43.2,289,3-5-2015
E,49,501,3-5-2015
I used console.log(data) to check, and I found that AtTime has null value.... I do not why..Anyone could help me with this? Thanks!
It's one character in your time format string.
//var parseDate = d3.time.format("%d-%m-%y").parse; // lower-case Y expects two digits only
var parseDate = d3.time.format("%d-%m-%Y").parse; // use capital Y for 4 digit years
see https://github.com/d3/d3/wiki/Time-Formatting#format for all the different modifiers
There is a mistake in your dates, I parsed them and ordered them so the line would render correctly.
data.forEach(function(d) {
var dateArr = d.AtTime.split('-');
d.AtTime = new Date(+dateArr[2], +dateArr[1], +dateArr[0]);
d.Temperature = +d.Temperature;
})
data.sort(function(a, b) {
return new Date(b.AtTime) - new Date(a.AtTime);
});
Remove the implicit number cast in your valueLine function:
var valueline = d3.svg.line()
.x(function(d) {
return x(d.AtTime);
})
.y(function(d) {
return y(d.Temperature);
});
And finally if you don't have any css add a stroke to your line so it renders:
svg.append("path")
.attr("class", "line")
.attr('stroke', 'red')
.attr("d", valueline(data));
Working plnkr: https://plnkr.co/edit/ujFDtHkdtC2EeBwJ1foU?p=preview

d3.js array issues: Invalid value for <path> in line graph

Fiddle (updating it now): http://jsfiddle.net/hy6r1peb/
I'm attempting to plot points via line graph based on the following data pulled from a JSON API:
var data = {
"january": [
{"total": "31", "date": "2015-01-01"},
{"total": "19", "date": "2015-01-05"},
{"total": "4", "date": "2015-01-10"}
], "error": false, "status": 200
};
This is my code from the d3noobs tutorial. It throws an error on line 1 of d3.js. Where have I gone wrong?
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%Y-%m-%d").parse;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
// Adds the svg canvas
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.json(URL, function(error, data) {
if (error) return console.warn(error);
else {
data = data.january;
data.forEach(function(d) {
d.date = parseDate(d.date);
d.total = +d.total;
});
}
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.total; })]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
I typo'd and had d.close in there when I shouldn't have. Doing this purely to close the question -- all credit goes to Terry for his sharp eyes.

Problems rendering line graph in D3

I'm attempting to learn D3 by following some of the simple bl.ock examples. One of the examples uses a CSV file to create a line graph.
I'm using this JSON file to create the path for the graph. The code below outputs the correct data to the console, but when I try to append the data (d.date, d.rain) to the x and y domains, nothing displays.
To the console...
// hold the daily rain total
var daily_rain_total;
// get the data
d3.json("data.json", function(error, data) {
// log the returned object on console unless error
if (error) return console.error(error);
console.log(data);
days = data.data.weather;
// step through each day
days.forEach(function(d) {
hourly = d.hourly;
hourly.forEach(function(h) {
daily_rain_total = daily_rain_total + parseFloat(h.precipMM);
});
d.date = d.date;
console.log(d.date);
d.rain = daily_rain_total.toFixed(2);
console.log(d.rain);
// reset total
daily_rain_total = 0;
});
});
Render a line graph...
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.rain); });
// Adds the svg canvas
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 + ")");
// hold the daily rain total
var daily_rain_total;
// get the data
d3.json("data.json", function(error, data) {
// log the returned object on console unless error
if (error) return console.error(error);
console.log(data);
days = data.data.weather;
// step through each day
days.forEach(function(d) {
// step through each hour
hourly = d.hourly;
hourly.forEach(function(h) {
daily_rain_total = daily_rain_total + parseFloat(h.precipMM);
});
d.date = d.date;
console.log(d.date);
d.rain = daily_rain_total.toFixed(2);
console.log(d.rain);
// reset total
daily_rain_total = 0;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.rain; })]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
Any tips are greatly appreciated.

Categories

Resources