D3.js 行正在返回一个随机数
D3.js line is returning a random number
首先说明我是 D3 的新手,这可能是我遗漏的一个简单错误 - 我知道它必须是。我尝试访问数据的方式有些问题。
想弄清楚这个人有一段时间了。 (可能是我看得太久了)
我玩弄它直到我的行 finally 出现了,但现在它没有显示完整的行,只有两个点 - 我不确定是数字的。
提前致谢!
编辑:目标是使用 lineData[0] 沿 lineData1 (months). Eventually, lineData2 的 x 轴绘制一条线将用于第二条线,但只是试图让第一条线起作用目前
编辑:可以在此处找到更新的代码(根据 Shashank 的建议):
https://codepen.io/anon/pen/RevxYG?editors=0010
我更新后的图表看起来好多了,但仍然看到 NaN 值:
这是我的代码:
let lineData = [
[4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"]
]
console.log("lineData", lineData)
// set dimensions of the line chart
let width = 393,
height = 285;
// set the scales
let yScale = d3.scaleLinear()
.domain([0, 52])
.range([height - 40 , 0]);
let xScale = d3.scaleOrdinal()
.range([0, width - 40]);
// create the line
let line = d3.line()
.x(function(d, i) { return xScale(i); })
.y(function(d) { return yScale(d[0]); });
// create svg container
let lineChart = d3.select(element)
.append("svg")
.attr("viewbox", "0 60 960 600")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("width", width)
.attr("height", height)
.attr("class", "line-chart")
lineChart.append("path")
.datum(lineData)
.attr("d", line)
.attr("fill", "none")
.attr("stroke", "rebeccapurple")
.attr("stroke-width", 2)
lineChart.selectAll("dot")
.data(lineData)
.attr("d", line)
.enter()
.append("circle")
.attr("r", 3.5)
.attr("cx", function(d, i) { return xScale(i)})
.attr("cy", function(d) { return yScale(d[0])})
.attr("fill", "rebeccapurple")
lineChart.append("g")
.attr("transform", "translate(20, 245)")
.call(d3.axisBottom(xScale))
lineChart.append("g")
.attr("transform", "translate(20, 0)")
.call(d3.axisLeft(yScale))
正在通过函数传入数据。
数据是:
我的图表如下所示:
和我生成的 path/dots 看起来像:
漏分:
- 重要提示:理想情况下,您应该在此处使用 d3 time scale as you're looking to plot a line based on months. But an ordinal scale would work too. I'm guessing you're looking for d3.scaleBand。
Band scales are like ordinal scales except the output range is continuous and numeric.
为什么不用d3.scaleOrdinal
?这是一个例子:
let lineData = [
[4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"]
]
let xScale = d3.scaleOrdinal().range(lineData[2])
.domain(lineData[0]);
console.log('domain is: ' + xScale.domain());
console.log('range is: ' + xScale.range());
<script src="https://d3js.org/d3.v4.min.js"></script>
你会看到重复的值是如何映射到月份的,这对你的情况没有帮助,所以 d3.scaleBand()
(你也可以尝试使用 d3.scalePoint
。
使用上面的波段比例,您设置的域将是 lineData[2]
,方法如下:
xScale = d3.scaleBand().domain(lineData[2])
转换未应用于 line
和 circles
。所以我附加了 <g>
容器来分别包含直线和圆圈,并转换了这些组元素。例如:
var dots = lineChart.append('g')
.attr("transform", "translate(20, 0)");
下面的解决方案只是回答了这个关于将第一行附加到图表的具体问题。正如您在评论中提到的,您最终会将第二个元素添加为另一行,path
选择会改变
let lineData = [
[4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"]
]
// set dimensions of the line chart
let width = 393,
height = 285;
// set the scales
let yScale = d3.scaleLinear()
.domain([0, 52])
.range([height - 40 , 0]);
let xScale = d3.scaleBand().domain(lineData[2])
.rangeRound([0, width - 40]);
// create the line
let line = d3.line()
.x(function(d, i) {
return xScale(lineData[2][i]) + xScale.bandwidth()/2;
})
.y(function(d) { return yScale(d); });
// create svg container
let lineChart = d3.select('body')
.append("svg")
.attr("viewbox", "0 60 960 600")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("width", width)
.attr("height", height)
.attr("class", "line-chart")
var lineG = lineChart.append('g')
.attr("transform", "translate(20, 0)");
lineG.append("path")
.data(lineData)
.attr("d", line)
.attr("fill", "none")
.attr("stroke", "rebeccapurple")
.attr("stroke-width", 2)
var dots = lineChart.append('g')
.attr("transform", "translate(20, 0)");
dots.selectAll("dot")
.data(lineData[0])
.enter()
.append("circle").classed('dot', true)
.attr("r", 3.5)
.attr("cx", function(d, i) { return xScale(lineData[2][i]) + xScale.bandwidth()/2})
.attr("cy", function(d) { return yScale(d)})
.attr("fill", "rebeccapurple")
lineChart.append("g")
.attr("transform", "translate(20, 245)")
.call(d3.axisBottom(xScale))
lineChart.append("g")
.attr("transform", "translate(20, 0)")
.call(d3.axisLeft(yScale))
<script src="https://d3js.org/d3.v4.min.js"></script>
建议:像 yScale
[0,52] 那样将域设置为静态值不是一个好的做法。尝试使用 d3.extent or d3.min 方法。
希望这对您有所帮助。
编辑: 当您尝试使用 d3.scalePoint
时,您在 line
函数中选择 xScale 值时犯了一个小错误和圈子。您需要在 fn 行中选择 categories[i]
,如下所示:
.x(function(d, i) {
return xScale(categories[i]);
})
使用 d3.scalePoint
更新了片段
let data = {
'New': [4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
'Terminated': [0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0]
};
let categories = ["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"];
let lineData = [data.New, data.Terminated, categories];
// set dimensions of the line chart
let width = 393,
height = 285;
// set the scales
let yScale = d3.scaleLinear()
.domain([0, 60]).nice()
.range([height - 40 , 0]);
let xScale = d3.scalePoint()
.domain(lineData[2].map(function(d, i) { return d; }))
.range([0, width - 40]);
// create the line
let line = d3.line()
.x(function(d, i) {
return xScale(categories[i]);
})
.y(function(d) { return yScale(d); });
// create svg container
let lineChart = d3.select('body')
.append("svg")
.attr("viewbox", "0 60 960 600")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("width", width)
.attr("height", height)
.attr("class", "line-chart")
var lineG = lineChart.append('g')
.attr("transform", "translate(20, 0)");
lineG.append("path")
.datum(lineData)
.attr("d", function(d) { return line(d[0]); })
.attr("fill", "none")
.attr("stroke", "rebeccapurple")
.attr("stroke-width", 2)
lineChart.selectAll("dot")
.data(lineData[0])
.enter()
.append("circle")
.attr("transform", "translate(20, 0)")
.attr("r", 3.5)
.attr("cx", function(d, i) { return xScale(categories[i])})
.attr("cy", function(d) { return yScale(d)})
.attr("fill", "rebeccapurple")
lineChart.append("g")
.attr("transform", "translate(20, 245)")
.call(d3.axisBottom(xScale))
lineChart.append("g")
.attr("transform", "translate(20, 0)")
.call(d3.axisLeft(yScale))
<script src="https://d3js.org/d3.v4.min.js"></script>
希望这也能有所帮助。
首先说明我是 D3 的新手,这可能是我遗漏的一个简单错误 - 我知道它必须是。我尝试访问数据的方式有些问题。
想弄清楚这个人有一段时间了。 (可能是我看得太久了)
我玩弄它直到我的行 finally 出现了,但现在它没有显示完整的行,只有两个点 - 我不确定是数字的。
提前致谢!
编辑:目标是使用 lineData[0] 沿 lineData1 (months). Eventually, lineData2 的 x 轴绘制一条线将用于第二条线,但只是试图让第一条线起作用目前
编辑:可以在此处找到更新的代码(根据 Shashank 的建议): https://codepen.io/anon/pen/RevxYG?editors=0010
我更新后的图表看起来好多了,但仍然看到 NaN 值:
这是我的代码:
let lineData = [
[4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"]
]
console.log("lineData", lineData)
// set dimensions of the line chart
let width = 393,
height = 285;
// set the scales
let yScale = d3.scaleLinear()
.domain([0, 52])
.range([height - 40 , 0]);
let xScale = d3.scaleOrdinal()
.range([0, width - 40]);
// create the line
let line = d3.line()
.x(function(d, i) { return xScale(i); })
.y(function(d) { return yScale(d[0]); });
// create svg container
let lineChart = d3.select(element)
.append("svg")
.attr("viewbox", "0 60 960 600")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("width", width)
.attr("height", height)
.attr("class", "line-chart")
lineChart.append("path")
.datum(lineData)
.attr("d", line)
.attr("fill", "none")
.attr("stroke", "rebeccapurple")
.attr("stroke-width", 2)
lineChart.selectAll("dot")
.data(lineData)
.attr("d", line)
.enter()
.append("circle")
.attr("r", 3.5)
.attr("cx", function(d, i) { return xScale(i)})
.attr("cy", function(d) { return yScale(d[0])})
.attr("fill", "rebeccapurple")
lineChart.append("g")
.attr("transform", "translate(20, 245)")
.call(d3.axisBottom(xScale))
lineChart.append("g")
.attr("transform", "translate(20, 0)")
.call(d3.axisLeft(yScale))
正在通过函数传入数据。
数据是:
我的图表如下所示:
和我生成的 path/dots 看起来像:
漏分:
- 重要提示:理想情况下,您应该在此处使用 d3 time scale as you're looking to plot a line based on months. But an ordinal scale would work too. I'm guessing you're looking for d3.scaleBand。
Band scales are like ordinal scales except the output range is continuous and numeric.
为什么不用d3.scaleOrdinal
?这是一个例子:
let lineData = [
[4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"]
]
let xScale = d3.scaleOrdinal().range(lineData[2])
.domain(lineData[0]);
console.log('domain is: ' + xScale.domain());
console.log('range is: ' + xScale.range());
<script src="https://d3js.org/d3.v4.min.js"></script>
你会看到重复的值是如何映射到月份的,这对你的情况没有帮助,所以 d3.scaleBand()
(你也可以尝试使用 d3.scalePoint
。
使用上面的波段比例,您设置的域将是
lineData[2]
,方法如下:xScale = d3.scaleBand().domain(lineData[2])
转换未应用于
line
和circles
。所以我附加了<g>
容器来分别包含直线和圆圈,并转换了这些组元素。例如:var dots = lineChart.append('g') .attr("transform", "translate(20, 0)");
下面的解决方案只是回答了这个关于将第一行附加到图表的具体问题。正如您在评论中提到的,您最终会将第二个元素添加为另一行,path
选择会改变
let lineData = [
[4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
[0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0],
["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"]
]
// set dimensions of the line chart
let width = 393,
height = 285;
// set the scales
let yScale = d3.scaleLinear()
.domain([0, 52])
.range([height - 40 , 0]);
let xScale = d3.scaleBand().domain(lineData[2])
.rangeRound([0, width - 40]);
// create the line
let line = d3.line()
.x(function(d, i) {
return xScale(lineData[2][i]) + xScale.bandwidth()/2;
})
.y(function(d) { return yScale(d); });
// create svg container
let lineChart = d3.select('body')
.append("svg")
.attr("viewbox", "0 60 960 600")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("width", width)
.attr("height", height)
.attr("class", "line-chart")
var lineG = lineChart.append('g')
.attr("transform", "translate(20, 0)");
lineG.append("path")
.data(lineData)
.attr("d", line)
.attr("fill", "none")
.attr("stroke", "rebeccapurple")
.attr("stroke-width", 2)
var dots = lineChart.append('g')
.attr("transform", "translate(20, 0)");
dots.selectAll("dot")
.data(lineData[0])
.enter()
.append("circle").classed('dot', true)
.attr("r", 3.5)
.attr("cx", function(d, i) { return xScale(lineData[2][i]) + xScale.bandwidth()/2})
.attr("cy", function(d) { return yScale(d)})
.attr("fill", "rebeccapurple")
lineChart.append("g")
.attr("transform", "translate(20, 245)")
.call(d3.axisBottom(xScale))
lineChart.append("g")
.attr("transform", "translate(20, 0)")
.call(d3.axisLeft(yScale))
<script src="https://d3js.org/d3.v4.min.js"></script>
建议:像 yScale
[0,52] 那样将域设置为静态值不是一个好的做法。尝试使用 d3.extent or d3.min 方法。
希望这对您有所帮助。
编辑: 当您尝试使用 d3.scalePoint
时,您在 line
函数中选择 xScale 值时犯了一个小错误和圈子。您需要在 fn 行中选择 categories[i]
,如下所示:
.x(function(d, i) {
return xScale(categories[i]);
})
使用 d3.scalePoint
更新了片段let data = {
'New': [4, 2, 0, 3, 3, 4, 52, 3, 0, 3, 3, 1],
'Terminated': [0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0]
};
let categories = ["Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep"];
let lineData = [data.New, data.Terminated, categories];
// set dimensions of the line chart
let width = 393,
height = 285;
// set the scales
let yScale = d3.scaleLinear()
.domain([0, 60]).nice()
.range([height - 40 , 0]);
let xScale = d3.scalePoint()
.domain(lineData[2].map(function(d, i) { return d; }))
.range([0, width - 40]);
// create the line
let line = d3.line()
.x(function(d, i) {
return xScale(categories[i]);
})
.y(function(d) { return yScale(d); });
// create svg container
let lineChart = d3.select('body')
.append("svg")
.attr("viewbox", "0 60 960 600")
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("width", width)
.attr("height", height)
.attr("class", "line-chart")
var lineG = lineChart.append('g')
.attr("transform", "translate(20, 0)");
lineG.append("path")
.datum(lineData)
.attr("d", function(d) { return line(d[0]); })
.attr("fill", "none")
.attr("stroke", "rebeccapurple")
.attr("stroke-width", 2)
lineChart.selectAll("dot")
.data(lineData[0])
.enter()
.append("circle")
.attr("transform", "translate(20, 0)")
.attr("r", 3.5)
.attr("cx", function(d, i) { return xScale(categories[i])})
.attr("cy", function(d) { return yScale(d)})
.attr("fill", "rebeccapurple")
lineChart.append("g")
.attr("transform", "translate(20, 245)")
.call(d3.axisBottom(xScale))
lineChart.append("g")
.attr("transform", "translate(20, 0)")
.call(d3.axisLeft(yScale))
<script src="https://d3js.org/d3.v4.min.js"></script>
希望这也能有所帮助。