Reputation: 95
I'm trying to get my data to show up in my graph, however I get an error that says that my data is "NaN" after I converted the Year and Miles column from strings to integers.
I'm guessing that it's something with my x_scale & y_scale...?
<!DOCTYPE html>
<html lang="en">
<head>
<description>
<!--charts - avg vehicle trip per mile, source: http://nhts.ornl.gov/2009/pub/stt.pdf-->
</description>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<link rel="stylesheet" href="/bootstrap-3.3.7-dist/css/bootstrap.min.css">
<script type="text/javascript" src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script type="text/javascript">
// global variables
var dataset;
d3.csv("avgVehicleTripLengthMiles.csv", function (error, data) {
if (error) {
console.log(error);
} else {
console.log(data);
}
// once loaded, data is copied to dataset because js is asynchronous
dataset = data;
createScatterplot();
});
/*
function typeConv() {
// type conversion from string to integer
var typeConv = dataset.forEach(function (d) {
d["Year"] = +d["Year"];
d["Miles"] = +d["Miles"];
return d;
});
}
*/
function createScatterplot() {
// TEST
var typeConv = dataset.forEach(function (d) {
d["Year"] = +d["Year"];
d["Miles"] = +d["Miles"];
return d;
});
var title = d3.select("body")
.append("h4")
.text("Avg. Vehicle Trip Length per Mile");
// dimensions of canvas
var padding = 30;
var margin = {
top: 20,
right: 40,
bottom: 20,
left: 40
},
w = 800 - margin.left - margin.right,
h = 400 - margin.top - margin.bottom;
// create svg canvas
var svg_canvas = d3.select("body")
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom);
// create scale for axis
var x_scale = d3.scaleLinear().domain([1969, 2009]).range([padding, w - padding * 2]);
var y_scale =
d3.scaleLinear().domain([0, 20]).range([h - padding, padding]);
// r_scale created specifically for circles' radius to be mapped unto axes
var r_scale =
d3.scaleLinear().domain([0, d3.max(dataset, function (d) {
return d[1];
})]).range([0, 20]);
// define axis & ticks // .ticks(5) to x_axis and .ticks(1) to y_axis
var x_axis = d3.axisBottom().scale(x_scale);
var y_axis = d3.axisLeft().scale(y_scale);
// create group, "g" element, to create x_axis and y_axis
var x_group = svg_canvas.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(x_axis);
var y_group = svg_canvas.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",0)")
.call(y_axis);
// create circles
svg_canvas.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function (d) {
return x_scale(d[0]);
})
.attr("cy", function (d) {
console.log(d); // TEST
return y_scale(d[1]);
})
.attr("cr", function (d) {
return r_scale(d[1]);
});
}
</script>
</body>
</html>
Upvotes: 0
Views: 58
Reputation: 95
// global variables
var dataset;
d3.csv("avgVehicleTripLengthMiles.csv", function (error, data) {
if (error) {
console.log(error);
} else {
console.log(data);
}
// once loaded, data is copied to dataset because js is asynchronous
dataset = data;
createScatterplot();
});
function createScatterplot() {
// TEST
var typeConv = dataset.forEach(function (d) {
// d["Year"] = +d["Year"];
d["Miles"] = +d["Miles"];
// return d;
});
var title = d3.select("body")
.append("h4")
.text("Avg. Vehicle Trip Length per Mile");
// dimensions of canvas
var padding = 30;
var margin = {
top: 20,
right: 40,
bottom: 20,
left: 40
},
w = 800 - margin.left - margin.right,
h = 400 - margin.top - margin.bottom;
// create svg canvas
var svg_canvas = d3.select("body")
.append("svg")
.attr("width", w + margin.left + margin.right)
.attr("height", h + margin.top + margin.bottom);
// create scale for axis
var x_scale = d3.scaleLinear().domain([1965, 2009]).range([padding, w - padding * 2]);
var y_scale =
d3.scaleLinear().domain([0, 20]).range([h - padding, padding]);
// r_scale created specifically for circles' radius to be mapped unto axes
var r_scale =
d3.scaleLinear().domain([0, d3.max(dataset, function (d) {
return d[1];
})]).range([0, 20]);
// define axis & ticks // .ticks(5) to x_axis and .ticks(1) to y_axis
var x_axis = d3.axisBottom().scale(x_scale);
var y_axis = d3.axisLeft().scale(y_scale);
// create group, "g" element, to create x_axis and y_axis
var x_group = svg_canvas.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(x_axis);
var y_group = svg_canvas.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",0)")
.call(y_axis);
// create & color circles
svg_canvas.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function (d) {
return x_scale(d["Year"]);
})
.attr("cy", function (d) {
return y_scale(d["Miles"]);
})
.attr("r", function (d) {
return 5;
})
.style("fill", function (d) {
if (d["Trip Purpose"] === "All Purposes") {
return "pink";
} else if (d["Trip Purpose"] === "To or From Work") {
return "red";
} else if (d["Trip Purpose"] === "Shopping") {
return "blue";
} else if (d["Trip Purpose"] === "Other Family/Personal Errands") {
return "green";
} else if (d["Trip Purpose"] === "Social and Recreational") {
return "gray";
};
});
// create text label for x-axis
svg_canvas.append("text")
.attr("x", w / 2)
.attr("y", h + margin.top + 20)
.style("text-anchor", "middle")
.text("Year");
// create text label for y-axis
svg_canvas.append("text")
.attr("transform", "rotate(-90)")
.attr("x", (0 - margin.left / 2))
.attr("y", (h/2))
.style("text-anchor", "middle")
.text("Miles");
Upvotes: 0
Reputation: 1173
There are several issues, and I'll try to step through them one by one.
In order to test, I had to make up my own data. My test CSV file looked like this (so your final answer might change slightly if your file is different)
Year,Miles
2006,5.0
2007,7.2
2008,19.3
As was pointed out by @altocumulus in the comments above, your .attr()
calls are referencing non-existant indexes, which might be part of the trouble.
The radius attribute for circles is r
, not cr
I simplified the code by not calling a function for r
, but rather doing a static value. You may want to play further with this.
The significantly changed portion of code is
svg_canvas.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function (d) {
return x_scale(d["Year"]);
})
.attr("cy", function (d) {
return y_scale(d["Miles"]);
})
.attr("r", function (d) {
return 5;
//return r_scale(d[1]);
});
You still have an issue with the x-axis acting like numbers, and not dates, making 2006
look like 2,006
, for example. I haven't solved that issue here.
Lastly, I feel like you're complicating your code for no reason by trying to handle margin AND padding via the D3 code, when these end up meaning similar things in the Javascript context. I suggest accomplishing most of the margin/padding via CSS, which would simplify your code. Another example of an unnecessary complication is in the previous answer, below.
The return value of Array.forEach()
is undefined
, so it can't be assigned.
dataset.forEach(function (d) {
//d["Year"] = +d["Year"];
d["Miles"] = +d["Miles"];
// NOT NEEDED: return d;
});
If you need to keep your converted array separate, use Array.map()
.
Upvotes: 1