I want to update the point and axis as different option selection along with using tooltips. I select the value as a different option and select a different option. This code can also update the line with tooltips but when the line has updated the point of the previous line is exits but I want to remove those points when the line is updated.
var div = d3.select('body').append('div')
var margin = {top: 30, right: 30, bottom: 30, left: 50},
width = 600 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y-%m-%d").parse;
// var parseDate = d3.time.format("%d-%b-%y").parse;
var formatTime = d3.time.format("%e %B");
console.log(formatTime);
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)
// .tickFormat(formatPct)
.orient("left");
var line = d3.svg.line()
.x(function (d) {
return x(d.date);
})
.y(function (d) {
return y(d.pop);
});
var div = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);
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 dataFiltered = {};
var dataNested = {};
d3.csv("data2.csv", function (error, data) {
data.forEach(function (d) {
d.date = parseDate(d.year);
d.pop = +d.population;
d.value = +d.days;
});
var dataNested = d3.nest()
.key(function (d) {
return d.days
})
.entries(data)
div.append('select')
.attr('id', 'variableSelect')
.on('change', variableChange)
.selectAll('option')
.data(dataNested).enter()
.append('option')
.attr('value', function (d) {
return d.key
})
.text(function (d) {
return d.key
})
var dataFiltered = dataNested.filter(function (d) {
return d.key === d3.select('#variableSelect').property('value')
})
x.domain(d3.extent(dataFiltered[0].values, function (d) {
return d.date;
}));
y.domain(d3.extent(dataFiltered[0].values, function (d) {
return d.pop;
}));
// svg.append("path")
// .attr("class", "line")
// .attr("d", line(data));
// svg.select("dot")
// .data(data)
// .enter().append("circle")
// .attr("r", 4)
// .attr("cx", function (d) {
// return x(d.date);
// })
// .attr("cy", function (d) {
// return y(d.pop);
// })
function toolstip(div) {
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 5)
.attr("cx", function (d) {
return x(d.date);
})
.attr("cy", function (d) {
return y(d.pop);
})
.on("mouseover", function (d) {
div.transition()
.duration(200)
.style("opacity", .9);
div.html(formatTime(d.date) + "," + d.pop)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function (d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
}
toolstip(div);
// xFormat = "%d-%m-%y";
svg.append("g")
.attr("class", "xAxis")
.attr("transform", "translate(0," + height + ")")
// .call(d3.axisBottom(xAxis).tickFormat(d3.timeFormat(xFormat)));
.call(xAxis);
svg.append("g")
.attr("class", "yAxis")
.call(yAxis)
// .call(d3.axisLeft(yAxis))
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end");
// .text("Cumulative Return");
svg.append("path")
.datum(dataFiltered[0].values)
.attr("class", "line")
.attr("d", line);
function variableChange() {
var value = this.value;
var dataFiltered = dataNested.filter(function (d) {
return d.key === value
})
console.log(dataFiltered);
x.domain(d3.extent(dataFiltered[0].values, function (d) {
return d.date;
}));
y.domain(d3.extent(dataFiltered[0].values, function (d) {
return d.pop;
}));
toolstip();
// svg.selectAll("dot")
d3.select('.xAxis').transition().duration(1000).call(xAxis)
d3.select('.yAxis').transition().duration(1000).call(yAxis)
d3.select('.line').datum(dataFiltered[0].values).attr('d', line)
}
}
);
I'm trying to add a brush filter to my line graph and I follow this example but, I get errors.
Error: attribute d: Expected number, "MNaN,NaNLNaN,NaNC…".
Error: attribute d: Expected number, "M0,NaNL0.1167307672…".
Here's my code:
var margin = {top: 20, right: 20, bottom: 110, left: 50},
width = 900 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom,
margin2 = { top: 430, right: 20, bottom: 30, left: 50 },
height2 = 500 - margin2.top - margin2.bottom;
var parseTime = d3.timeParse("%Y-%m-%d");
var x = d3.scaleTime().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
x2 = d3.scaleTime().range([0, width]),
y2 = d3.scaleLinear().range([height2, 0]);
var xAxis = d3.axisBottom(x)
yAxis = d3.axisLeft(y)
xAxis2 = d3.axisBottom(x2);
var color = d3.scaleOrdinal(d3.schemeCategory10);
var svg = d3.select("#plot").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
var plot = svg.append("g")
.attr("class", "plot")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var slider = svg.append("g")
.attr("class", "slider")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
var line = d3.line()
.curve(d3.curveBasis)
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.number); });
d3.csv("dataset.csv", function(error, data) {
var brush = d3.brushX()
.extent([[0,0], [width,height2]])
.on("brush end", brushed);
color.domain(d3.keys(data[0]).filter(function(key) {
return key !== "date";
}));
data.forEach(function(d) {
d.date = parseTime(d.date);
});
var countries = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
date: d.date,
number: +d[name]
};
})
};
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([d3.min(countries, function(c) { return d3.min(c.values, function(v) { return v.number; });}),
d3.max(countries, function(c) { return d3.max(c.values, function(v) { return v.number; });})]);
x2.domain(x.domain());
y2.domain(y.domain());
plot.append("path")
.datum(countries)
.attr("class", "lines")
.attr("d", line);
plot.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
plot.append("g")
.attr("class", "y axis")
.call(yAxis);
var country = plot.append("g");
country.selectAll(".country")
.data(countries)
.enter().append("g")
.attr("class", "country")
.attr("d", function(d) {
return line(d.values);
})
.style("stroke", function(d) {
return color(d.name);
});
slider.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
slider.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
function brushed() {
var selection = d3.event.selection;
if (selection !== null) {
var e = d3.event.selection.map(x2.invert, x2);
var test = plot.selectAll(".country");
test.classed("selected", function (d) {
return e[0] <= d.date && d.date <= e[1];
})
plot.selectAll(".lines")
.attr("d", line(
data.filter(function (d) { return e[0] <= d.date && e[1] >= d.date; })
));
}
}
});
And this is a sample of my dataset(it's too big):
date,Albania,Andorra,Armenia,Austria,Azerbaijan,Belarus,Belgium,Bosnia And Herzegovina,Bulgaria
2005-01-01,3.446,3.671,-4.206,-2.775,1.137,-1.384,4.136,0.213,1.874
2005-02-01,2.257,2.695,-3.321,-4.726,0.463,-6.487,1.729,-1.492,-0.656
2005-03-01,7.271,6.856,2.788,0.994,5.689,-3.512,6.753,4.393,4.499
2005-04-01,11.485,10.308,10.032,7.286,11.847,8.084,10.391,10.248,10.36
2005-05-01,17.294,14.866,14.285,12.238,17.047,13.555,13.473,15.811,15.937
2005-06-01,20.165,20.264,17.723,15.518,20.635,15.768,17.995,18.599,18.293
2005-07-01,23.338,21.591,23.476,16.729,25.517,19.528,18.586,21.085,21.461
2005-08-01,21.928,19.788,22.649,14.81,24.131,17.452,16.905,18.998,21.001
2005-09-01,19.071,16.95,17.586,13.266,20.089,14.207,16.449,16.803,17.261
2005-10-01,13.412,13.817,10.424,8.319,13.177,7.485,13.622,11.447,11.173
2005-11-01,8.167,6.996,4.515,1.016,7.571,1.62,5.913,5.734,5.448
2005-12-01,5.131,1.919,0.874,-3.361,4.944,-2.699,2.782,1.786,2.728
2006-01-01,1.822,3.566,-5.34,-6.262,-1.433,-8.192,0.834,-0.999,-2.194
2006-02-01,4.094,4.108,-1.693,-3.009,2.31,-8.342,2.114,1.6,0.408
2006-03-01,7.838,8.464,4.863,0.098,7.183,-2.922,4.215,4.918,5.608
2006-04-01,12.538,11.472,9.841,7.314,11.629,7.324,9.084,11.314,11.099
2006-05-01,16.826,15.313,14.616,11.521,16.346,12.832,14.243,15.371,15.644
2006-06-01,20.294,19.307,21.928,15.63,24.331,17.092,17.391,18.668,19.27
2006-07-01,23.107,24.003,21.551,19.81,23.873,20.188,22.837,22.206,21.414
2006-08-01,22.6,19.595,25.291,13.915,26.676,18.018,16.55,19.208,22.229
2006-09-01,19.095,18.205,17.931,14.806,19.721,14.03,18.334,17.298,17.472
2006-10-01,14.799,15.087,12.034,9.613,14.837,8.517,13.763,13.252,12.843
2006-11-01,7.687,10.358,3.482,3.927,6.643,2.978,8.608,6.889,6.877
2006-12-01,5.023,4.534,-3.862,-0.032,0.431,2.382,5.17,3.13,2.741
It seems that it has a problem with: .attr("d", line), but I'm getting confused.
Thank you in advance!
I managed to find a way to get rid of those errors. If it helps someone else, I've changed this:
plot.append("path")
.datum(countries)
.attr("class", "lines")
.attr("d", line);
plot.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
plot.append("g")
.attr("class", "y axis")
.call(yAxis);
var country = plot.append("g");
country.selectAll(".country")
.data(countries)
.enter().append("g")
.attr("class", "country")
.attr("d", function(d) {
return line(d.values);
})
.style("stroke", function(d) {
return color(d.name);
});
To this:
plot.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
plot.append("g")
.attr("class", "y axis")
.call(yAxis);
var country = plot.selectAll(".country")
.data(countries)
.enter().append("g")
.attr("class", "country");
country.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 add a zoom ability to a historical line chart I've built using a custom data object. I've been using http://codepen.io/brantwills/pen/igsoc/ as a template. The chart is rendered but when I try zooming there are two errors:
Error: Invalid value for path attribute d=""
Uncaught TypeError: undefined is not a function (in the last transform, translate of the last part of the zoomed function)
JSFiddle: http://jsfiddle.net/dshamis317/sFp6Q/
This is what my code looks like:
function renderHistoricalData(data) {
var parseDate = d3.time.format("%Y%m%d").parse;
data.forEach(function(d) { d.date = parseDate(d.date); });
// data.sort(function(a,b) { return a.date - b.date; });
var margin = {top: 20, right: 80, bottom: 30, left: 50},
width = 1200 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var zoom = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([1, 10])
.on("zoom", zoomed);
var line = d3.svg.line()
.interpolate("basis")
// .defined(function(d) { return d.y!=0; })
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.sentiment); });
var svg = d3.select("#historical_chart").append("svg")
.call(zoom)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; }));
var sites = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {date: d.date, sentiment: +d[name]};
})
};
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(sites, function(c) { return d3.min(c.values, function(v) { return v.sentiment; }); }),
d3.max(sites, function(c) { return d3.max(c.values, function(v) { return v.sentiment; }); })
]);
var site = svg.selectAll(".site")
.data(sites)
.enter().append("g")
.attr("class", "site");
site.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name); });
site.append("text")
.attr("transform", function(d) {
var val = d.values[d.values.length-1];
return "translate(" + x(val.date) + "," + y(val.sentiment) + ")";
})
.attr("x", 3)
.attr("dy", ".35em")
.style("text-anchor", "start")
.text(function(d) { return d.name; });
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("Sentiment (%)");
function zoomed() {
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
svg.selectAll('path.line').attr('d', line);
sites.selectAll('.site').attr("transform", function(d) {
return "translate(" + x(d.date) + "," + y(d.sentiment) + ")"; }
);
}
}
Thank you!
Alright, let's walk through each thing.
To start with, in zoomed, the last transform doesn't need to be there. In the original, it's there to move the circles, which you don't have.
Also important, your edit on path.line sets d to the wrong function. If you look at what you're setting d to when you first make it, it should be the same, as a general rule of thumb, so it should be function(d) { return line(d.values); }, not just line.
Now, for the actual reason it's disappearing.
Your scale extent is calculated based off the original domain. However, you don't set the domain until AFTER you call scaleExtent, which means your scaling is all based on the default. It's not actually disappearing, it's being compressed to the left hand side of the graph. If you remove your x axis, you'll see the colored smear of all your data flattened against the side.
Move all your domain calculations to above where you build your scale, and it'll be fine.
To make things a bit more concrete:
function renderHistoricalData(data) {
var parseDate = d3.time.format("%Y%m%d").parse;
data.forEach(function(d) { d.date = parseDate(d.date); });
// data.sort(function(a,b) { return a.date - b.date; });
var margin = {top: 20, right: 80, bottom: 30, left: 50},
width = 1200 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; }));
var sites = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {date: d.date, sentiment: +d[name]};
})
};
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(sites, function(c) { return d3.min(c.values, function(v) { return v.sentiment; }); }),
d3.max(sites, function(c) { return d3.max(c.values, function(v) { return v.sentiment; }); })
]);
var zoom = d3.behavior.zoom()
.x(x)
.y(y)
.scaleExtent([1, 10])
.on("zoom", zoomed);
var line = d3.svg.line()
.interpolate("basis")
// .defined(function(d) { return d.y!=0; })
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.sentiment); });
var svg = d3.select("#historical_chart").append("svg")
.call(zoom)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var site = svg.selectAll(".site")
.data(sites)
.enter().append("g")
.attr("class", "site");
site.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name); });
site.append("text")
.attr("transform", function(d) {
var val = d.values[d.values.length-1];
return "translate(" + x(val.date) + "," + y(val.sentiment) + ")";
})
.attr("x", 3)
.attr("dy", ".35em")
.style("text-anchor", "start")
.text(function(d) { return d.name; });
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("Sentiment (%)");
function zoomed() {
svg.select(".x.axis").call(xAxis);
svg.select(".y.axis").call(yAxis);
svg.selectAll('path.line').attr('d', function(d) { return line(d.values); });
}
}
If you want to text to move, you can give it an easily identifiable class, and then update it in zoomed.
Giving it a class:
site.append("text")
.attr("class", "lineLabel")
Updating it in zoomed:
svg.selectAll(".lineLabel")
.attr("transform", function(d) {
var val = d.values[d.values.length-1];
return "translate(" + x(val.date) + "," + y(val.sentiment) + ")";
});
This will just make it follow the ends of the lines, but you can modify whatever attributes you like to get the wanted effects.
I am trying to replicate the Multi-Series Line Chart example but I am unable to get the labels to show up at the end of the line or at all for that matter. The code is basically all the same as the example but a few words changed. The dataset is of county population and is formatted the same as in the example, earliest date at the top of the list and most recent date at the bottom of the list.
Anyone see anything I'm missing??
var margin = {top: 20, right: 80, 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 x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.population); });
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("historicalpopulationTest.csv", function(error, data) {
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; }));
data.forEach(function(d) {
d.date = parseDate(d.date);
});
var counties = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {date: d.date, population: +d[name]};
})
};
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(counties, function(c) { return d3.min(c.values, function(v) { return v.population; }); }),
d3.max(counties, function(c) { return d3.max(c.values, function(v) { return v.population; }); })
]);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("x", width)
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Year");
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("Population");
var county = svg.selectAll(".county")
.data(counties)
.enter().append("g")
.attr("class", "county");
county.append("path")
.attr("class", "line")
.attr("d", function(d) { return line(d.values); })
.style("stroke", function(d) { return color(d.name); });
county.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.date) + "," + y(d.value.population) + ")"; })
.attr("x", width)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
});
Graph looks like this
I think your problem is in the following code
county.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.date) + "," + y(d.value.population) + ")"; })
.attr("x", width)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
I haven't run your code, but it looks like you are translating the text to the end of the line and then moving the x position an additional 'width' number of pixels.
Try changing .attr("x", width) to .attr("x", 3)
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.