Javascript d3:将最小/最大/平均线添加到现有折线图

Javascript d3:将最小/最大/平均线添加到现有折线图,javascript,d3.js,Javascript,D3.js,我有一个d3折线图,其中有一组线显示了每个站点随时间变化的趋势。我想再增加3行,显示每个日期所有站点的最小值、最大值和平均值。我尝试按日期嵌套数据,并使用d3.mean/max/min创建一个新的数据数组,如下所示: var minMaxMean = d3.nest() .key(function(d) { return d.starttime }) .rollup(function(d) { return { mean: d3.mean(d, fun

我有一个d3折线图,其中有一组线显示了每个站点随时间变化的趋势。我想再增加3行,显示每个日期所有站点的最小值、最大值和平均值。我尝试按日期嵌套数据,并使用d3.mean/max/min创建一个新的数据数组,如下所示:

var minMaxMean = d3.nest()
    .key(function(d) { return d.starttime })
    .rollup(function(d) {
      return {
        mean: d3.mean(d, function(g) { return g.roll_pm25; }),
        max: d3.max(d, function(g) { return g.roll_pm25; }),
        min: d3.min(d, function(g) { return g.roll_pm25; })
      };
    })
    .entries(data);

但现在我被卡住了。如何将此数据添加到具有现有x轴和y轴的现有折线图中?嵌套数据是正确的方法吗?”这是密码。我遇到的问题在第118-139行。

很酷的问题;这很难回答。你在正确的轨道上完成了你的巢穴和卷起,但还有几件事。首先,鸟巢似乎强迫你追溯到一个字符串。虽然这对嵌套很好,但当它调用
xScale
时,会发生不好的事情。其次,嵌套似乎失去了对数据的排序。第三,您需要三行,但要在一次运行中生成所有行。我是这样做的:

var minMaxMean = d3.nest()
    .key(function(d) { return d.starttime; })
    .rollup(function(d) {
      return {
        starttime: d[0].starttime,
        mean: d3.mean(d, function(g) { return g.roll_pm25; }),
        max: d3.max(d, function(g) { return g.roll_pm25; }),
        min: d3.min(d, function(g) { return g.roll_pm25; })
      };
    })
    .entries(data)
    // all we want are the values now
    .map(function(d){
        return d.values;
    });

// have to re-sort
minMaxMean.sort(function(a,b){
    return a.starttime - b.starttime;
}) 

// 3 lines for mean, min, and max 
svg.append("path")
  .attr("d", 
    d3.svg.line()
        .x(function(d) { return xScale(d.starttime); })
      .y(function(d) { return yScale(d.mean); })(minMaxMean)
  )
  .style("stroke","green")
  .style("fill", "none");

svg.append("path")
  .attr("d", 
    d3.svg.line()
        .x(function(d) { return xScale(d.starttime); })
      .y(function(d) { return yScale(d.max); })(minMaxMean)
  )
  .style("stroke","red")
  .style("fill", "none");

svg.append("path")
  .attr("d",
    d3.svg.line()
        .x(function(d) { return xScale(d.starttime); })
      .y(function(d) { return yScale(d.min); })(minMaxMean)
  )
  .style("stroke","blue")
  .style("fill", "none");
更新

var保证金={
前20名,
右:20,,
底数:20,
左:50
};
//变量宽度=900-margin.left-margin.right,
//高度=500-margin.top-margin.bottom;
var graphic=d3.选择(“图表”);
var width=graphic.node().clientWidth-margin.left-margin.right,
高度=300-margin.top-margin.bottom;
xScale=d3.time.scale()
.范围([0,宽度]);
var yScale=d3.scale.linear()
.范围([高度,0]);
var xAxis=d3.svg.axis()
.scale(xScale)
.orient(“底部”)
.1尺寸(高度)
.1(10)
.outerTickSize(3)
.tickFormat(d3.time.format(“%m/%d”);
var yAxis=d3.svg.axis()
.刻度(yScale)
.东方(“左”)
.innerTickSize(-宽度)
.1(10)
.outerTickSize(3)
.点号格式(d3轮);
var svg=d3.选择(“图表”).追加(“svg”)
.attr(“宽度”,宽度+边距。左侧+边距。右侧)
.attr(“高度”,高度+边距。顶部+边距。底部)
.附加(“g”)
.attr(“转换”、“平移”(+margin.left+)、“+margin.top+”);
var parseDate=d3.time.format(“%m/%d/%Y%H:%m”).parse;
d3.csv(“https://raw.githubusercontent.com/Kaz-A/pm25/master/data/RealTime_02112016.csv“,准备就绪);
功能就绪(错误、数据){
如果(错误)返回控制台。警告(错误);
data.forEach(函数(d){
d、 滚转pm25=+d.滚转pm25;
d、 siteID=+d.siteID;
d、 starttime=parseDate(d.starttime);
});
xScale.domain(d3.extent)(数据,函数(d){
返回d.starttime;
}));
yScale.domain(d3.extent)(数据,函数(d){
返回d.roll_pm25;
}));
var nestedBySite=d3.nest()
.键(功能(d){
返回d.SiteID;
})
.排序键(d3.升序)
.条目(数据);
var lineGroup=svg.selectAll(“.g-group”)
.数据(由站点嵌套)
.输入()
.附加(“g”)
.attr(“类别”、“g集团”);
var line=d3.svg.line()
.x(功能(d){
返回xScale(d.starttime);
})
.y(功能(d){
返回Y刻度(d.roll_pm25);
});
lineGroup.append(“路径”)
.attr(“类别”、“g线”)
.attr(“d”,函数(d){
返回线(d值);
});
//添加x轴和y轴
svg.append(“g”)
.attr(“类”、“x轴”)
.attr(“变换”、“平移(0)”、“高度+”)
.呼叫(xAxis);
svg.append(“g”)
.attr(“类”、“y轴”)
.呼叫(yAxis);
//将平均线、最大线和最小线添加到折线图中
//按starttime嵌套数据,并将平均值、最大值和最小值添加到数组中
var minMaxMean=d3.nest()
.key(函数(d){返回d.starttime;})
.汇总(功能(d){
返回{
开始时间:d[0]。开始时间,
mean:d3.mean(d,函数(g){返回g.roll_pm25;}),
max:d3.max(d,函数(g){返回g.roll_pm25;}),
min:d3.min(d,函数(g){返回g.roll_pm25;})
};
})
.条目(数据)
.地图(功能(d){
返回d值;
});
minMaxMean.sort(函数(a,b){
返回a.starttime-b.starttime;
}) 
追加(“路径”)
.attr(“d”,
d3.svg.line()
.x(函数(d){return xScale(d.starttime);})
.y(函数(d){返回yScale(d.mean);})(minMaxMean)
)
.style(“笔划”、“绿色”)
.样式(“填充”、“无”);
追加(“路径”)
.attr(“d”,
d3.svg.line()
.x(函数(d){return xScale(d.starttime);})
.y(函数(d){return yScale(d.max);})(minMaxMean)
)
.style(“笔划”、“红色”)
.样式(“填充”、“无”);
追加(“路径”)
.attr(“d”,
d3.svg.line()
.x(函数(d){return xScale(d.starttime);})
.y(函数(d){返回yScale(d.min);})(minMaxMean)
)
.style(“笔划”、“蓝色”)
.样式(“填充”、“无”);
//调整大小
d3.选择(窗口).on(“调整大小”,resizeHandler);
函数resizeHandler(){
log(“调整大小!!”);
宽度=graphic.node().clientWidth-margin.left-margin.right;
X刻度范围([0,宽度]);
xAxisGroup.call(xAxis);
lineGroup.attr(“路径”,函数(d){
返回xScale(d.starttime);
});
console.log(“更新宽度”,宽度);
};
}
正文{
字体系列:arial,sans;
字体大小:11px;
宽度:600px;
利润率:40px自动;
}
#图表{
高度:300px;
}
.轴线{
填充:无;
笔画:黑色;
笔划阵列:2px 3px;
形状渲染:边缘清晰;
笔画宽度:1px;
}
.轴路径{
显示:无;
}
g线{
冲程:#ccc;
填充:无;
笔画宽度:1px;
}
g色线{
笔画:钢蓝;
填充:无;
笔画宽度:2px;
}
.g-line.g-secondary-line{
行程:#f0;
}
.勾线{
不透明度:0.1;
}
.min-max-mean_线{
笔画:红色;
}


这太棒了!!!非常感谢你的帮助!这在很大程度上是有意义的,但我仍然对必须重新排序嵌套数据感到困惑,因为我不必重新排序现有行的数据,即使它也使用嵌套数据…@Kaz-a,我也对此感到困惑。我认为这与日期被强制回到嵌套中的字符串有关。