Reputation: 469
Okay, for the following code, my line function for x is returning NaN. I have no clue why. I tried changing the Time values to 1 through 9 and used a linear scale, I have converted them to times (it's just for a proof of concept, so the values can be adjusted for the time being), and tried them a 'New Date', no luck.
What am I doing wrong? Why is X always NaN?
A sample of one of the logged data points:
x:d is : 2015-06-01 x(new Date(d.Period)) is NaN y:d is 65.54347826086956
jQuery(document).ready(function ($) {
var margin = {top: 20, right: 30, bottom: 40, left: 50},
width = 300 - margin.left - margin.right,
height = 150 - margin.top - margin.bottom;
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 color = d3.scale.category10();
var line = d3.svg.line()
.x(function(d) {console.log('d is : ', d.Period,' x(new Date(d.Period)) is ', x(new Date(d.Period))); return x(new Date(d.Period)); })
.y(function(d) {console.log('y:d is ', y(d.Value)); return y(d.Value); })
var svg = d3.select("#pipeline-chart-render")
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
// This separates the data into the lines we want, although the data is stored
// In the same original object.
var keys = color.domain(d3.keys(data[0].values[0]).filter(function(key) {
if (key === 'Amount'
|| key === 'Quantity') {
return key
}
}));
// This returns the data into two separate objects which can be graphed.
// In this case, Amount and Quantity.
var datasets = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {Period: d.values[0].Time, Value: +d.values[0][name]};
})
};
});
console.log('datasets is: ', datasets);
// set the minYDomainValue to zero instead of letting it be a lingering magic number.
var minDomainValue = 0
// x.domain([
// minDomainValue,
// d3.max(datasets, function(c) { return d3.max(c.values, function(v) { console.log(v); return v.Time }); })
// ])
x.domain(d3.extent(datasets, function(d) { console.log(d); return new Date(d.values[0].Time); }));
y.domain([
minDomainValue,
// d3.min(datasets, function(c) { return d3.min(c.values, function(v) { return v.Time; }); }),
d3.max(datasets, function(c) { return d3.max(c.values, function(v) { return v.Value; }); })
])
// Append the x-axis class and move axis around.
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
// Append the y-axis class.
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
var dataset = svg.selectAll('.pipeline')
.data(datasets);
console.log(dataset);
dataset.enter()
.append('g')
.attr('class', 'pipeline');
dataset.append('path')
.attr('class', 'line')
.attr('d', function(d) { return line(d.values); })
.attr("data-legend",function(d) { return d.name})
.style("stroke", function(d) { return color(d.name); })
dataset.exit().remove()
});
var data = [
{
key: 1,
values: [
{
Amount: 33,
Quantity: 22,
Time: '2015-01-01'
}
]
},
{
key: 2,
values: [
{
Amount: 52,
Quantity: 20,
Time: '2015-02-01'
}
]
},
{
key: 3,
values: [
{
Amount: 63,
Quantity: 30,
Time: '2015-03-01'
}
]
},
{
key: 4,
values: [
{
Amount: 92,
Quantity: 60,
Time: '2015-04-01'
}
]
},
{
key: 5,
values: [
{
Amount: 50,
Quantity: 29,
Time: '2015-05-01'
}
]
},
{
key: 6,
values: [
{
Amount: 53,
Quantity: 25,
Time: '2015-06-01'
}
]
},
{
key: 7,
values: [
{
Amount: 46,
Quantity: 12,
Time: '2015-07-01'
}
]
},
{
key: 8,
values: [
{
Amount: 52,
Quantity: 15,
Time: '2015-08-01'
}
]
},
{
key: 9,
values: [
{
Amount: 55,
Quantity: 20,
Time: '2015-09-01'
}
]
}
]
// var formatTime = function(date) {
// var formatter = d3.time.format("%Y-%m").parse;
// return formatter(date);
// }
Upvotes: 1
Views: 2081
Reputation: 108512
To answer your specific question, you aren't setting the x domain properly, I'd recommend this:
var minDate = d3.min(datasets, function(d0){
return d3.min(d0.values, function(d1){
return d1.Period;
})
}),
maxDate = d3.max(datasets, function(d0){
return d3.max(d0.values, function(d1){
return d1.Period;
})
});
x.domain([minDate, maxDate]);
For that to work, take my next advice and stop the new Date(
madness, just coerce your times in to dates from the get-go. I highly recommend you use d3.time.format instead of trying to do the conversion your self:
var tP = d3.time.format("%Y-%m-%d");
// This returns the data into two separate objects which can be graphed.
// In this case, Amount and Quantity.
var datasets = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
Period: tP.parse(d.values[0].Time), //<-- just convert once!
Value: +d.values[0][name]
};
})
};
});
You line function is then simplified to:
var line = d3.svg.line()
.x(function(d) {
return x(d.Period);
})
.y(function(d) {
return y(d.Value);
});
Full code:
<!DOCTYPE html>
<html>
<head>
<script data-require="[email protected]" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<svg id="pipeline-chart-render"></div>
<script>
var data = [{
key: 1,
values: [{
Amount: 33,
Quantity: 22,
Time: '2015-01-01'
}]
}, {
key: 2,
values: [{
Amount: 52,
Quantity: 20,
Time: '2015-02-01'
}]
}, {
key: 3,
values: [{
Amount: 63,
Quantity: 30,
Time: '2015-03-01'
}]
}, {
key: 4,
values: [{
Amount: 92,
Quantity: 60,
Time: '2015-04-01'
}]
}, {
key: 5,
values: [{
Amount: 50,
Quantity: 29,
Time: '2015-05-01'
}]
}, {
key: 6,
values: [{
Amount: 53,
Quantity: 25,
Time: '2015-06-01'
}]
}, {
key: 7,
values: [{
Amount: 46,
Quantity: 12,
Time: '2015-07-01'
}]
}, {
key: 8,
values: [{
Amount: 52,
Quantity: 15,
Time: '2015-08-01'
}]
}, {
key: 9,
values: [{
Amount: 55,
Quantity: 20,
Time: '2015-09-01'
}]
}]
var margin = {
top: 20,
right: 30,
bottom: 40,
left: 50
},
width = 300 - margin.left - margin.right,
height = 150 - margin.top - margin.bottom;
var tP = d3.time.format("%Y-%m-%d");
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 color = d3.scale.category10();
var line = d3.svg.line()
.x(function(d) {
console.log('d is : ', d.Period, ' x(new Date(d.Period)) is ', x(d.Period));
return x(d.Period);
})
.y(function(d) {
console.log('y:d is ', y(d.Value));
return y(d.Value);
})
var svg = d3.select("#pipeline-chart-render")
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
// This separates the data into the lines we want, although the data is stored
// In the same original object.
var keys = color.domain(d3.keys(data[0].values[0]).filter(function(key) {
if (key === 'Amount' || key === 'Quantity') {
return key
}
}));
// This returns the data into two separate objects which can be graphed.
// In this case, Amount and Quantity.
var datasets = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {
Period: tP.parse(d.values[0].Time),
Value: +d.values[0][name]
};
})
};
});
// set the minYDomainValue to zero instead of letting it be a lingering magic number.
var minDomainValue = 0;
var minDate = d3.min(datasets, function(d0){
return d3.min(d0.values, function(d1){
return d1.Period;
})
}),
maxDate = d3.max(datasets, function(d0){
return d3.max(d0.values, function(d1){
return d1.Period;
})
});
x.domain([minDate, maxDate]);
y.domain([
minDomainValue,
// d3.min(datasets, function(c) { return d3.min(c.values, function(v) { return v.Time; }); }),
d3.max(datasets, function(c) {
return d3.max(c.values, function(v) {
return v.Value;
});
})
])
// Append the x-axis class and move axis around.
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
// Append the y-axis class.
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
var dataset = svg.selectAll('.pipeline')
.data(datasets);
console.log(dataset);
dataset.enter()
.append('g')
.attr('class', 'pipeline');
dataset.append('path')
.attr('class', 'line')
.attr('d', function(d) {
return line(d.values);
})
.attr("data-legend", function(d) {
return d.name
})
.style("stroke", function(d) {
return color(d.name);
})
dataset.exit().remove()
</script>
</body>
</html>
Upvotes: 1