我有一个包含空值的时间序列折线图,因此在我的线条中留下了空白。我想要做的是选择性地让 d3 线生成器忽略空值并跨越间隙。
如图所示,蓝色系列有间隙。
我的部分问题是我已经对这种数据格式进行了标准化:
[
{"x":1397102460000,"y0":11.4403,"y1":96.5},
{"x":1397139660000,"y0":13.1913,"y1":96.5},
{"x":1397522940000,"y1":96.5},
...
]
因此,当一个系列具有特定时间戳的读数时,另一个系列具有空值。
最终,我可以尝试通过在绘制之前过滤我的数据来解决这个问题,但我希望有一个更聪明的解决方案,也许是关于线生成器的。
我的线生成器非常简单:
line = d3.line()
.x(function(d) {
return ~~_this.x(d[xKey]);
})
.y(function(d) {
return ~~_this.y(d[yKey]);
})
.defined(function(d) {
return d[yKey] || d[yKey] === 0;
});
如果我删除我的 defined
方法,线条会连接起来,但 null y 值会被解释为 0px 而不是不存在。
有没有办法告诉线生成器不要在空数据处包含一个点?
我还应该注意,我使用的是 d3 v4.x。
最佳答案
假设您希望这条线从最后一个有效点到下一个有效点,作为一条直线,最好的想法是按照评论中的建议过滤您的数据。
line.defined
在行中创建间隙,这是预期的行为,也是此函数的用途。
因此,如果您不想过滤数据并且不想创建间隙(使用defined
),您可以更改线生成器函数。这不是一个好主意,它是一段丑陋的代码,但它是可行的。
设置一个计数器:
var counter;
如果值有效 (!= null
),增加计数器。如果不是,则告诉行生成器保留最后一个有效值:
var line = d3.line()
.x((d, i) => {
if (data[i].y) {
return xScale(d.x)
} else {
return xScale(data[counter].x)
}
})
.y((d, i) => {
if (d.y) {
counter = i;
return yScale(d.y)
} else {
return yScale(data[counter].y)
}
});
在此演示中,该行从第五个数据点(最后一个有效值)跳到第九个数据点(下一个有效值):
var w = 500,
h = 300;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
var data = [{
x: 10,
y: 50
}, {
x: 20,
y: 70
}, {
x: 30,
y: 20
}, {
x: 40,
y: 60
}, {
x: 50,
y: 40
}, {
x: 60,
y: null
}, {
x: 70,
y: null
}, {
x: 80,
y: null
}, {
x: 90,
y: 90
}, {
x: 100,
y: 20
}];
var xScale = d3.scaleLinear()
.domain([0, 100])
.range([30, w - 20]);
var yScale = d3.scaleLinear()
.domain([0, 100])
.range([h - 20, 20]);
var counter;
var line = d3.line()
.x((d, i) => {
if (data[i].y) {
return xScale(d.x)
} else {
return xScale(data[counter].x)
}
})
.y((d, i) => {
if (d.y) {
counter = i;
return yScale(d.y)
} else {
return yScale(data[counter].y)
}
});
svg.append("path")
.attr("d", line(data))
.attr("stroke-width", 2)
.attr("stroke", "teal")
.attr("fill", "none");
var xAxis = d3.axisBottom(xScale);
var yAxis = d3.axisLeft(yScale);
svg.append("g")
.attr("transform", "translate(0," + (h - 20) + ")")
.call(xAxis);
svg.append("g")
.attr("transform", "translate(30,0)")
.call(yAxis);
<script src="https://d3js.org/d3.v4.min.js"></script>
关于javascript - 强制 d3 折线图忽略空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40873931/