2016-03-31 18 views
0

私はd3線図を持っています。私は、各日付のすべてのサイトの最小値、最大値および平均値を示す3行を追加したいと思います。私は、日付によってデータを入れ子にし、このようにデータの新しい配列を作成するために、d3.mean /最大/最小を使用してみました:d3:既存の折れ線グラフに最小/最大/平均線を追加する

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軸で追加するにはどうすればよいですか?ネストデータは正しいアプローチですか?コードはHereです。私が持っている問題は118-139行目です。

答えて

0

クールな質問;それは驚くほど答えにくいです。あなたはあなたの巣とロールアップで正しいトラックにありますが、カップルのものです。まず、ネストはあなたを強制的にストリングに戻すようです。これは巣にとっては問題ありませんが、電話するときはxScaleが悪いことが起こります。第二に、ネストはあなたのデータのソートを失うようです。第3に、3行が必要ですが、すべての行を1回で生成しようとしています。ここで私はそれを行うだろう方法は次のとおりです。

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"); 

fiddleを更新しました。

var margin = { 
 
    top: 20, 
 
    right: 20, 
 
    bottom: 20, 
 
    left: 50 
 
}; 
 

 
//var width = 900 - margin.left - margin.right, 
 
// height = 500 - margin.top - margin.bottom; 
 

 

 
var graphic = d3.select("#chart"); 
 

 
var width = graphic.node().clientWidth - margin.left - margin.right, 
 
    height = 300 - margin.top - margin.bottom; 
 

 
xScale = d3.time.scale() 
 
    .range([0, width]); 
 

 
var yScale = d3.scale.linear() 
 
    .range([height, 0]); 
 
    
 
var xAxis = d3.svg.axis() 
 
    .scale(xScale) 
 
    .orient("bottom") 
 
    .innerTickSize(-height) 
 
    .tickPadding(10) 
 
    .outerTickSize(3) 
 
    .tickFormat(d3.time.format("%m/%d")); 
 

 
var yAxis = d3.svg.axis() 
 
    .scale(yScale) 
 
    .orient("left") 
 
    .innerTickSize(-width) 
 
    .tickPadding(10) 
 
    .outerTickSize(3) 
 
    .tickFormat(d3.round); 
 

 
var svg = d3.select("#chart").append("svg") 
 
    .attr("width", width + margin.left + margin.right) 
 
    .attr("height", height + margin.top + margin.bottom) 
 
    .append("g") 
 
    .attr("transform", "translate(" + 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", ready); 
 

 
function ready(error, data) { 
 
    if (error) return console.warn(error); 
 

 
    data.forEach(function(d) { 
 
    d.roll_pm25 = +d.Roll_PM25; 
 
    d.siteID = +d.SiteID; 
 
    d.starttime = parseDate(d.StartTime); 
 
    }); 
 

 
    xScale.domain(d3.extent(data, function(d) { 
 
    return d.starttime; 
 
    })); 
 
    yScale.domain(d3.extent(data, function(d) { 
 
    return d.roll_pm25; 
 
    })); 
 

 

 
    var nestedBySite = d3.nest() 
 
    .key(function(d) { 
 
     return d.SiteID; 
 
    }) 
 
    .sortKeys(d3.ascending) 
 
    .entries(data); 
 

 
    var lineGroup = svg.selectAll(".g-group") 
 
    .data(nestedBySite) 
 
    .enter() 
 
    .append("g") 
 
    .attr("class", "g-group"); 
 

 
    var line = d3.svg.line() 
 
    .x(function(d) { 
 
     return xScale(d.starttime); 
 
    }) 
 
    .y(function(d) { 
 
     return yScale(d.roll_pm25); 
 
    }); 
 

 

 
    lineGroup.append("path") 
 
    .attr("class", "g-line") 
 
    .attr("d", function(d) { 
 
     return line(d.values); 
 
    }); 
 

 
    //add x and y axis 
 
    svg.append("g") 
 
    .attr("class", "x axis") 
 
    .attr("transform", "translate(0," + height + ")") 
 
    .call(xAxis); 
 

 
    svg.append("g") 
 
    .attr("class", "y axis") 
 
    .call(yAxis); 
 
    
 
//add the mean, max and min lines to the linechart 
 
\t //nest data by starttime and add mean, max and min values to the array 
 
    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) 
 
    .map(function(d){ 
 
    \t return d.values; 
 
    }); 
 
    
 
minMaxMean.sort(function(a,b){ 
 
\t return a.starttime - b.starttime; 
 
}) 
 
    
 
svg.append("path") 
 
    .attr("d", 
 
    d3.svg.line() 
 
\t  .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() 
 
\t  .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() 
 
\t  .x(function(d) { return xScale(d.starttime); }) 
 
     .y(function(d) { return yScale(d.min); })(minMaxMean) 
 
) 
 
    .style("stroke","blue") 
 
    .style("fill", "none"); 
 

 
    //resize 
 
    d3.select(window).on("resize", resizeHandler); 
 

 
    function resizeHandler() { 
 
    console.log("resizing!!"); 
 
    width = graphic.node().clientWidth - margin.left - margin.right; 
 

 
    xScale.range([0, width]); 
 
    xAxisGroup.call(xAxis); 
 

 
    lineGroup.attr("path", function(d) { 
 
     return xScale(d.starttime); 
 
    }); 
 

 
    console.log("updated width", width); 
 
    }; 
 

 
}
body { 
 
    font-family: arial, sans; 
 
    font-size: 11px; 
 
    width: 600px; 
 
    margin: 40px auto; 
 
} 
 

 
#chart { 
 
    height: 300px; 
 
} 
 

 
.axis line { 
 
    fill: none; 
 
    stroke: black; 
 
    stroke-dasharray: 2px 3px; 
 
    shape-rendering: crispEdges; 
 
    stroke-width: 1px; 
 
} 
 

 
.axis path { 
 
    display: none; 
 
} 
 

 

 
.g-line { 
 
    stroke: #ccc; 
 
    fill: none; 
 
    stroke-width: 1px; 
 
} 
 

 
.g-color-line { 
 
    stroke: steelblue; 
 
    fill: none; 
 
    stroke-width: 2px; 
 
} 
 

 
.g-line.g-secondary-line { 
 
    stroke: #f0f0f0; 
 
} 
 

 
.tick line { 
 
    opacity: 0.1; 
 
} 
 

 
.min-max-mean_line { 
 
    stroke: red; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> 
 
<div id="chart"> 
 
</div>

+0

これは素晴らしいです!手伝ってくれてどうもありがとう!大部分は意味がありますが、ネストされたデータを使用していても既存のラインのデータを再ソートする必要がないため、また... –

+0

@ Kaz-A、私はそれについても混乱しています。私はそれが巣の中の文字列に強制的に戻されている日付と関係していると思う。 – Mark

関連する問題