Javascript 多系列图表-时间(年)间隔x轴叠加多年数据 背景

Javascript 多系列图表-时间(年)间隔x轴叠加多年数据 背景,javascript,d3.js,charts,Javascript,D3.js,Charts,我正在使用D34.x构建一个多系列折线图()来比较多年的年度数据,其中Y轴是全年可能值的范围,x轴表示01/01-12/31日期之间的时间间隔 问题 在构建此图表时,时间间隔似乎是特定于年份的,以防止不同年份的数据呈现在同一图表上。重申一下,目前的做法是每年在同一张图表上叠加;每年一行。要做到这一点,时间间隔是特定于年份的,需要大量(错误)的数据处理 在下面的示例图表中,我们可以看到2014年从左边开始(颜色:蓝色),2015年从右边继续(颜色:橙色)。我想看到的是这两个重叠在一起 确认/警告

我正在使用D34.x构建一个多系列折线图()来比较多年的年度数据,其中Y轴是全年可能值的范围,x轴表示01/01-12/31日期之间的时间间隔

问题 在构建此图表时,时间间隔似乎是特定于年份的,以防止不同年份的数据呈现在同一图表上。重申一下,目前的做法是每年在同一张图表上叠加;每年一行。要做到这一点,时间间隔是特定于年份的,需要大量(错误)的数据处理

在下面的示例图表中,我们可以看到2014年从左边开始(颜色:蓝色),2015年从右边继续(颜色:橙色)。我想看到的是这两个重叠在一起

确认/警告 通过将数据相互叠加(即多行,每行代表一年)来比较多年数据的一些复杂性已得到承认。例如,如何处理闰日年份与不闰日年份的比较。这在编程上使事情复杂化,但在视觉上不应该是一个问题

问题 1) 当一年刚刚过去时,使用时间间隔的最佳方法是什么

2) 有没有更好、更优雅的方法来创建多系列折线图,这些折线图表示的是相互叠加的多个年份,而不是将各个部分拼凑在一起

3) 有没有一种方法(不是静态的)可以从轴中删除年份(即2015年),而使用月份(一月)


4) 是否可以将X轴上的文本向右移动(以编程方式),以便月份显示在刻度线之间(依我看,这在视觉上更准确)?

有几种方法可以解决此问题。事实上,它们太多了,以至于这个问题太宽泛了。当然,每种方法都有其优缺点。例如,一个简单的方法是完全删除时间刻度,并使用x轴的点刻度

我将建议一种不同的方法,稍微复杂一点,但仍然使用时间尺度:创建几个不同的时间尺度,每年一个。每一条线都有相同的范围:这样,每年的线可以重叠在一起

例如,从2013年到2017年:

var years = [2013, 2014, 2015, 2016, 2017];

var scales = {};

years.forEach(d => {
    scales["scale" + d] = d3.scaleTime()
        .domain([new Date(+d, 0, 1), new Date(+d, 11, 31)])
        .range([30, 470]);
});
这样,就可以继续使用x轴的时间刻度。问题是:时间尺度处理每一年,因为他们是:不同的。有些年份的天数更多,有些年份的天数更少。即使是白天也可能有更多或更少的小时

因此,我选择了一年(2017年),并在x轴上仅显示该年的月份。结果可能不是非常精确,但如果你在x轴上有整整一年的时间,这就足够了

这是演示。数据是随机生成的,每条线都是不同的年份(从2013年到2017年),从1月1日到12月31日:

var svg=d3.select(“body”).append(“svg”)
.attr(“宽度”,500)
.attr(“高度”,200);
var color=d3.scaleOrdinal(d3.schemeCategory 10);
今年的var;
var line=d3.line()
.x(d=>scales[今年](d.x))
.y(d=>yScale(d.y))
.曲线(d3.curveMonotoneX);
风险值年数=[2013、2014、2015、2016、2017];
var数据=[];
年。forEach((d,i)=>{
数据推送({
年份:d,
要点:[]
});
对于(var j=0;j<12;j++){
数据[i].points.push({
y:Math.random()*80+20,
x:新日期(d,j)
})
}
});
var尺度={};
var yScale=d3.scaleLinear()
.domain([01100])
.范围([170,30]);
年份。forEach(d=>{
刻度[“刻度”+d]=d3.scaleTime()
.domain([新日期(+d,0,1),新日期(+d,11,31)])
.范围([30470]);
});
var path=svg.selectAll(“foo”)
.数据(数据)
.输入()
.append(“路径”);
paths.attr(“笔划”,(d,i)=>颜色(i))
.attr(“d”,d=>{
今年=“规模”+d.年;
返回线(d点);
})
.attr(“填充”、“无”);
var xAxis=d3.axisBottom(scales.scale2017).tickFormat(d=>d3.timeFormat(“%b”)(d));
var yAxis=d3.轴左(yScale);
var gX=svg.append(“g”).attr(“transform”、“translate(0170)”).call(xAxis);
var gY=svg.append(“g”).attr(“transform”、“translate(30,0)”).call(yAxis)

两个问题和一个陈述。首先,如果引号内的文本(在本例中为“foo”)基本上可以是任何内容,并且图表仍然有效,那么在线
var path=svg.selectAll(“foo”)
的要点是什么?这不是我见过的唯一一个这样的例子。其次,
enter()
到底做什么?最后,我很欣赏这个例子。我没有考虑创建多个刻度,这是一种非常干净且显然正确的方法。我在这里写了一份文档,回答了您的两个问题:作为与问题相关的代码的记录,工作图表在很大程度上基于此答案,被标记并可供查看。