我正在尝试将我的数据显示在我的图表中,但是在我将Year和Miles列从字符串转换为整数后,我收到一条错误,指出我的数据是“NaN”。
我猜这是我的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>
答案 0 :(得分:1)
有几个问题,我会尝试逐一介绍它们。
为了测试,我不得不编制自己的数据。我的测试CSV文件看起来像这样(如果你的文件不同,你的最终答案可能会略有改变)
Year,Miles
2006,5.0
2007,7.2
2008,19.3
正如@altocumulus在上面的评论中指出的那样,您的.attr()
调用引用了不存在的索引,这可能是问题的一部分。
圈子的半径属性为r
,而不是cr
我通过不调用r
的函数来简化代码,而是执行静态值。你可能想要进一步发挥这个作用。
代码的重大变化部分是
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]);
});
例如,您仍然遇到x轴与数字相似而不是日期的问题,使2006
看起来像2,006
。我在这里没有解决这个问题。
最后,我觉得你通过D3代码尝试处理边距和填充而无缘无故地使代码变得复杂,当这些最终意味着Javascript上下文中的类似内容时。我建议通过CSS完成大部分边距/填充,这将简化您的代码。另一个不必要的并发症的例子在下面的答案中。
Array.forEach()
的返回值为undefined
,因此无法分配。
dataset.forEach(function (d) {
//d["Year"] = +d["Year"];
d["Miles"] = +d["Miles"];
// NOT NEEDED: return d;
});
如果您需要将转换后的数组分开,请使用Array.map()
。
答案 1 :(得分:0)
// 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");