【问题标题】:d3 multiline chart from JSON来自 JSON 的 d3 多线图
【发布时间】:2018-09-28 13:49:20
【问题描述】:

我有这个 JSON 结构:

[{
    "city": "roma",
    "giornata": [{"hour": 0, "vscore": 2.691172504799798, "sscore": 37476.67912706408}, {"hour": 1, "vscore": 2.691172504799798, "sscore": 37476.67912706408}, {"hour": 2, "vscore": 2.6911859886310534, "sscore": 37477.76228681598}, {"hour": 3, "vscore": 2.692891756586413, "sscore": 37633.63745016247}, {"hour": 4, "vscore": 2.7490858604464163, "sscore": 40331.835034215015}, {"hour": 5, "vscore": 3.6348376398556206, "sscore": 29087.830074293775}, {"hour": 6, "vscore": 5.227711033677134, "sscore": 40951.01373374646}, {"hour": 7, "vscore": 5.437638544676074, "sscore": 41884.0578795353}, {"hour": 8, "vscore": 5.478694300536231, "sscore": 41491.303030952506}, {"hour": 9, "vscore": 5.4692759563035125, "sscore": 41406.2244628412}, {"hour": 10, "vscore": 5.443814538954288, "sscore": 41843.69307948355}, {"hour": 11, "vscore": 5.422306701744998, "sscore": 41904.21264813825}, {"hour": 12, "vscore": 5.430029861802209, "sscore": 41834.62986331701}, {"hour": 13, "vscore": 5.4109556800533065, "sscore": 41794.032135620844}, {"hour": 14, "vscore": 5.40781751131936, "sscore": 41906.699275642364}, {"hour": 15, "vscore": 5.4276853171768575, "sscore": 42204.700654376065}, {"hour": 16, "vscore": 5.431391815372439, "sscore": 42038.98228259192}, {"hour": 17, "vscore": 5.452904669522696, "sscore": 42225.77758780385}, {"hour": 18, "vscore": 5.459166165306796, "sscore": 42521.80948063545}, {"hour": 19, "vscore": 5.4113071917201605, "sscore": 42211.7148629514}, {"hour": 20, "vscore": 5.346846713801516, "sscore": 40255.25859980825}, {"hour": 21, "vscore": 5.258902353621712, "sscore": 39863.6143315623}, {"hour": 22, "vscore": 5.099446294358522, "sscore": 38595.79782658543}, {"hour": 23, "vscore": 4.825210817812031, "sscore": 35445.99667251284}],
    "totale_vscore": 4.732977155119956,
    "totale_sscore": 39994.330896155014,
    "pop": 2953570.1564810127
}, {
    "city": "milan",
    "giornata": [{"hour": 0, "vscore": 2.82848132753263, "sscore": 32951.656649915116}, {"hour": 1, "vscore": 2.989182437431815, "sscore": 22400.365091162155}, {"hour": 2, "vscore": 3.089781672302136, "sscore": 25970.908167900478}, {"hour": 3, "vscore": 3.079852593000065, "sscore": 26122.539536044023}, {"hour": 4, "vscore": 3.127878555095266, "sscore": 28533.06300816934}, {"hour": 5, "vscore": 3.433688887459625, "sscore": 31280.682050177216}, {"hour": 6, "vscore": 4.460403545073164, "sscore": 41143.18408624148}, {"hour": 7, "vscore": 4.676520890455807, "sscore": 40440.9468380336}, {"hour": 8, "vscore": 4.5650214131720945, "sscore": 40922.767810551035}, {"hour": 9, "vscore": 4.534050693834924, "sscore": 40604.83122991684}, {"hour": 10, "vscore": 4.475014854496835, "sscore": 42008.856192005565}, {"hour": 11, "vscore": 4.449355201432976, "sscore": 40234.6533377194}, {"hour": 12, "vscore": 4.479651286256149, "sscore": 42297.87576207919}, {"hour": 13, "vscore": 4.532114009807487, "sscore": 42846.236555682415}, {"hour": 14, "vscore": 4.521175500387353, "sscore": 41932.90288440584}, {"hour": 15, "vscore": 4.462502028191485, "sscore": 41718.30395828536}, {"hour": 16, "vscore": 4.46901281686112, "sscore": 41710.48122672351}, {"hour": 17, "vscore": 4.5388217291954, "sscore": 40768.24927687489}, {"hour": 18, "vscore": 4.5271592249042865, "sscore": 41346.4872610591}, {"hour": 19, "vscore": 4.525012398546656, "sscore": 40461.46407886699}, {"hour": 20, "vscore": 4.4785954581843335, "sscore": 38842.93096854251}, {"hour": 21, "vscore": 4.300929936708735, "sscore": 36595.34193318566}, {"hour": 22, "vscore": 4.157413373148136, "sscore": 34567.45808410202}, {"hour": 23, "vscore": 4.097682551344804, "sscore": 32583.34061363281}],
    "totale_vscore": 4.116637599367636,
    "totale_sscore": 37011.89694171986,
    "pop": 2228858.085428001
}]

我需要创建一个 d3 折线图,其中每条线都是 JSON 的一个元素,例如:

“罗马”的一行,X 轴“小时”和 Y 轴“vscore”

“米兰”的第二行,X 轴“小时”和 Y 轴“vscore”

其他城市也是如此。

我的难点是从 json 动态创建 d3.svg.line()。

现在我的代码只有一行:

    var margin = {
            top: 20,
            right: 20,
            bottom: 50,
            left: 40
        },
        width = 900 - margin.left - margin.right,
        height = 290 - margin.top - margin.bottom;



    // Set the ranges
    var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], .1);


    var y = d3.scale.linear().range([height, 0]);

    // Define the axes
    var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom")
        .innerTickSize(-height)
        .outerTickSize(0)
        .tickPadding(10);

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left").innerTickSize(-width)
        .outerTickSize(0)
        .tickPadding(10);




        // Define the line

//Here I don't know how to get line dynamically
    var valueline = d3.svg.line()
    .interpolate("basis")
    .x(function (d) {
        return x(d.hour);
    })
    .y(function (d) {
        return y(d.vscore);
    });


        // Adds the svg canvas
        var svg = d3.select("#dailyChart")
            .append("svg")
            // .call(zoom)
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform",
                "translate(" + margin.left + "," + margin.top + ")");


                d3.json("data/ranking_sscore.json", function(error, data) {

                //Here I don't know how to cycle for get line from json

                    data = data[0].giornata

                    data.forEach(function (d) {

                            d.hour = d.hour;
                            d.vscore = +d.vscore;

                    });
                    x.domain(data.map(function (d) {
                        return d.hour;
                    }))
                    y.domain([0, d3.max(data,
                        function (d) {
                            return Math.max(d.vscore);
                        })]);

                  // Add the valueline path.
                    svg.append("path")
                    .attr("class", "line")
                    .attr("d", valueline(data))
                    .style("stroke", 1);

                  // Add the X Axis
                    svg.append("g")
                        .attr("class", "x axis")
                        .attr("transform", "translate(0," + height + ")")
                        .call(xAxis)
                        .selectAll("text")
                        .attr("y", 15)
                        .attr("x", 0)
                        .attr("dy", ".35em")


                    // Add the Y Axis
                    svg.append("g")
                        .attr("class", "y axis")
                        .call(yAxis);



    })

谢谢

【问题讨论】:

    标签: javascript json d3.js


    【解决方案1】:

    D3 可以为你做循环。

    这是一个 D3v5 版本。

    如果您想为许多城市着色,您可以使用color 序数比例,请参见注释行(您需要定义color)。

    var margin = { top: 20, right: 20, bottom: 50, left: 40 },
        svgWidth = 900,
        svgHeight = 290,
        width = svgWidth - margin.left - margin.right,
        height = svgHeight - margin.top - margin.bottom;
    
    var data = [{
        "city": "roma",
        "giornata": [
            {"hour": 0, "vscore": 2.691172504799798, "sscore": 37476.67912706408},
            {"hour": 1, "vscore": 2.691172504799798, "sscore": 37476.67912706408},
            {"hour": 2, "vscore": 2.6911859886310534, "sscore": 37477.76228681598},
            {"hour": 3, "vscore": 2.692891756586413, "sscore": 37633.63745016247},
            {"hour": 4, "vscore": 2.7490858604464163, "sscore": 40331.835034215015},
            {"hour": 5, "vscore": 3.6348376398556206, "sscore": 29087.830074293775},
            {"hour": 6, "vscore": 5.227711033677134, "sscore": 40951.01373374646},
            {"hour": 7, "vscore": 5.437638544676074, "sscore": 41884.0578795353},
            {"hour": 8, "vscore": 5.478694300536231, "sscore": 41491.303030952506},
            {"hour": 9, "vscore": 5.4692759563035125, "sscore": 41406.2244628412},
            {"hour": 10, "vscore": 5.443814538954288, "sscore": 41843.69307948355},
            {"hour": 11, "vscore": 5.422306701744998, "sscore": 41904.21264813825},
            {"hour": 12, "vscore": 5.430029861802209, "sscore": 41834.62986331701},
            {"hour": 13, "vscore": 5.4109556800533065, "sscore": 41794.032135620844},
            {"hour": 14, "vscore": 5.40781751131936, "sscore": 41906.699275642364},
            {"hour": 15, "vscore": 5.4276853171768575, "sscore": 42204.700654376065},
            {"hour": 16, "vscore": 5.431391815372439, "sscore": 42038.98228259192},
            {"hour": 17, "vscore": 5.452904669522696, "sscore": 42225.77758780385},
            {"hour": 18, "vscore": 5.459166165306796, "sscore": 42521.80948063545},
            {"hour": 19, "vscore": 5.4113071917201605, "sscore": 42211.7148629514},
            {"hour": 20, "vscore": 5.346846713801516, "sscore": 40255.25859980825},
            {"hour": 21, "vscore": 5.258902353621712, "sscore": 39863.6143315623},
            {"hour": 22, "vscore": 5.099446294358522, "sscore": 38595.79782658543},
            {"hour": 23, "vscore": 4.825210817812031, "sscore": 35445.99667251284}],
        "totale_vscore": 4.732977155119956,
        "totale_sscore": 39994.330896155014,
        "pop": 2953570.1564810127
    }, {
        "city": "milan",
        "giornata": [
            {"hour": 0, "vscore": 2.82848132753263, "sscore": 32951.656649915116},
            {"hour": 1, "vscore": 2.989182437431815, "sscore": 22400.365091162155},
            {"hour": 2, "vscore": 3.089781672302136, "sscore": 25970.908167900478},
            {"hour": 3, "vscore": 3.079852593000065, "sscore": 26122.539536044023},
            {"hour": 4, "vscore": 3.127878555095266, "sscore": 28533.06300816934},
            {"hour": 5, "vscore": 3.433688887459625, "sscore": 31280.682050177216},
            {"hour": 6, "vscore": 4.460403545073164, "sscore": 41143.18408624148},
            {"hour": 7, "vscore": 4.676520890455807, "sscore": 40440.9468380336},
            {"hour": 8, "vscore": 4.5650214131720945, "sscore": 40922.767810551035},
            {"hour": 9, "vscore": 4.534050693834924, "sscore": 40604.83122991684},
            {"hour": 10, "vscore": 4.475014854496835, "sscore": 42008.856192005565},
            {"hour": 11, "vscore": 4.449355201432976, "sscore": 40234.6533377194},
            {"hour": 12, "vscore": 4.479651286256149, "sscore": 42297.87576207919},
            {"hour": 13, "vscore": 4.532114009807487, "sscore": 42846.236555682415},
            {"hour": 14, "vscore": 4.521175500387353, "sscore": 41932.90288440584},
            {"hour": 15, "vscore": 4.462502028191485, "sscore": 41718.30395828536},
            {"hour": 16, "vscore": 4.46901281686112, "sscore": 41710.48122672351},
            {"hour": 17, "vscore": 4.5388217291954, "sscore": 40768.24927687489},
            {"hour": 18, "vscore": 4.5271592249042865, "sscore": 41346.4872610591},
            {"hour": 19, "vscore": 4.525012398546656, "sscore": 40461.46407886699},
            {"hour": 20, "vscore": 4.4785954581843335, "sscore": 38842.93096854251},
            {"hour": 21, "vscore": 4.300929936708735, "sscore": 36595.34193318566},
            {"hour": 22, "vscore": 4.157413373148136, "sscore": 34567.45808410202},
            {"hour": 23, "vscore": 4.097682551344804, "sscore": 32583.34061363281}],
        "totale_vscore": 4.116637599367636,
        "totale_sscore": 37011.89694171986,
        "pop": 2228858.085428001
    }];
    
    // Set the ranges
    var x = d3.scaleLinear().range([0, width]);
    
    var y = d3.scaleLinear().range([height, 0]);
    
    // Define the axes
    var xAxis = d3.axisBottom()
        .scale(x)
        .tickSize(-height);
    
    var yAxis = d3.axisLeft()
        .scale(y)
        .tickSize(-width);
    
    var valueline = d3.line()
        .curve(d3.curveBasis)
        .x( d => x(d.hour) )
        .y( d => y(d.vscore) );
    
    // Adds the svg canvas
    var g = d3.select("#dailyChart")
        .append("svg")
        // .call(zoom)
        .attr("width", svgWidth)
        .attr("height", svgHeight)
        .append("g")
        .attr("transform", `translate(${margin.left},${margin.top})`);
    
    // d3.json("data/ranking_sscore.json", drawGraph );
    
    drawGraph(null, data);
    
    function drawGraph(error, data) {
    
        x.domain(d3.extent(data[0].giornata, d => d.hour));
        y.domain([0, d3.max(data, d => d3.max(d.giornata, g => g.vscore) ) + 1 ]);
    
        // Add the X Axis
        g.append("g")
            .attr("class", "x axis")
            .attr("transform", `translate(0,${height})`)
            .call(xAxis)
            .selectAll("text")
            .attr("y", 15)
            .attr("x", 0)
            .attr("dy", ".35em");
    
        // Add the Y Axis
        g.append("g")
            .attr("class", "y axis")
            .call(yAxis);
    
        g.selectAll(".city")
         .data(data)
         .enter()
           .append("path")
           .attr('class', d => 'city' + ' ' + d.city)
           //.style("stroke", (d,i) => color(i) )
           .attr("d", d => valueline(d.giornata) );
    }
    .roma {
      fill:none;
      stroke:red;
    }
    .milan {
      fill:none;
      stroke:blue;
    }
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <div id="dailyChart"></div>

    【讨论】:

    • 我想这应该是正确/接受的答案
    【解决方案2】:

    您必须先在主数组上循环,然后在每个数组“gionarta”上循环

    window.addEventListener('load', function () {
    var margin = {
      top: 20,
      right: 20,
      bottom: 50,
      left: 40
    },
      width = 900 - margin.left - margin.right,
      height = 290 - margin.top - margin.bottom;
    
    // Set the ranges
    var x = d3.scale.ordinal()
      .rangeRoundBands([0, width], .1);
    
    var y = d3.scale.linear().range([height, 0]);
    
    // Define the axes
    var xAxis = d3.svg.axis()
      .scale(x)
      .orient("bottom")
      .innerTickSize(-height)
      .outerTickSize(0)
      .tickPadding(10);
    
    var yAxis = d3.svg.axis()
      .scale(y)
      .orient("left").innerTickSize(-width)
      .outerTickSize(0)
      .tickPadding(10);
    
    // Define the line
    
    //Here I don't know how to get line dynamically
    var valueline = d3.svg.line()
      .interpolate("basis")
      .x(function (d) {
        return x(d.hour);
      })
      .y(function (d) {
        return y(d.vscore);
      });
    
    
    // Adds the svg canvas
    var svg = d3.select("#dailyChart")
      .append("svg")
    // .call(zoom)
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform","translate(" + margin.left + "," + margin.top + ")");
    
    
    
    //Here is the relevant part first loop on your main array
    
    data.forEach(function(el,index){
      items = el.giornata;
    // then on each array giornata
      items.forEach(function (d) {
    
        d.hour = d.hour;
        d.vscore = +d.vscore;
    
      });
      x.domain(items.map(function (d) {
        return d.hour;
      }))
      y.domain([0, d3.max(items,
      function (d) {
        return Math.max(d.vscore);
      })]);
    
    // Add the valueline path.
      svg.append("path")
        .attr("class", "line roma  "+data[index].city)
        .attr("d", valueline(items))
        .style("stroke", 1);
    
    });
    
    // Add the X Axis
    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis)
      .selectAll("text")
      .attr("y", 15)
      .attr("x", 0)
      .attr("dy", ".35em")
    
    
    // Add the Y Axis
    svg.append("g")
      .attr("class", "y axis")
      .call(yAxis);
    });
    
    						
    var data = [{
        "city": "roma",
        "giornata": [{"hour": 0, "vscore": 2.691172504799798, "sscore": 37476.67912706408}, {"hour": 1, "vscore": 2.691172504799798, "sscore": 37476.67912706408}, {"hour": 2, "vscore": 2.6911859886310534, "sscore": 37477.76228681598}, {"hour": 3, "vscore": 2.692891756586413, "sscore": 37633.63745016247}, {"hour": 4, "vscore": 2.7490858604464163, "sscore": 40331.835034215015}, {"hour": 5, "vscore": 3.6348376398556206, "sscore": 29087.830074293775}, {"hour": 6, "vscore": 5.227711033677134, "sscore": 40951.01373374646}, {"hour": 7, "vscore": 5.437638544676074, "sscore": 41884.0578795353}, {"hour": 8, "vscore": 5.478694300536231, "sscore": 41491.303030952506}, {"hour": 9, "vscore": 5.4692759563035125, "sscore": 41406.2244628412}, {"hour": 10, "vscore": 5.443814538954288, "sscore": 41843.69307948355}, {"hour": 11, "vscore": 5.422306701744998, "sscore": 41904.21264813825}, {"hour": 12, "vscore": 5.430029861802209, "sscore": 41834.62986331701}, {"hour": 13, "vscore": 5.4109556800533065, "sscore": 41794.032135620844}, {"hour": 14, "vscore": 5.40781751131936, "sscore": 41906.699275642364}, {"hour": 15, "vscore": 5.4276853171768575, "sscore": 42204.700654376065}, {"hour": 16, "vscore": 5.431391815372439, "sscore": 42038.98228259192}, {"hour": 17, "vscore": 5.452904669522696, "sscore": 42225.77758780385}, {"hour": 18, "vscore": 5.459166165306796, "sscore": 42521.80948063545}, {"hour": 19, "vscore": 5.4113071917201605, "sscore": 42211.7148629514}, {"hour": 20, "vscore": 5.346846713801516, "sscore": 40255.25859980825}, {"hour": 21, "vscore": 5.258902353621712, "sscore": 39863.6143315623}, {"hour": 22, "vscore": 5.099446294358522, "sscore": 38595.79782658543}, {"hour": 23, "vscore": 4.825210817812031, "sscore": 35445.99667251284}],
        "totale_vscore": 4.732977155119956,
        "totale_sscore": 39994.330896155014,
        "pop": 2953570.1564810127
    }, {
        "city": "milan",
        "giornata": [{"hour": 0, "vscore": 2.82848132753263, "sscore": 32951.656649915116}, {"hour": 1, "vscore": 2.989182437431815, "sscore": 22400.365091162155}, {"hour": 2, "vscore": 3.089781672302136, "sscore": 25970.908167900478}, {"hour": 3, "vscore": 3.079852593000065, "sscore": 26122.539536044023}, {"hour": 4, "vscore": 3.127878555095266, "sscore": 28533.06300816934}, {"hour": 5, "vscore": 3.433688887459625, "sscore": 31280.682050177216}, {"hour": 6, "vscore": 4.460403545073164, "sscore": 41143.18408624148}, {"hour": 7, "vscore": 4.676520890455807, "sscore": 40440.9468380336}, {"hour": 8, "vscore": 4.5650214131720945, "sscore": 40922.767810551035}, {"hour": 9, "vscore": 4.534050693834924, "sscore": 40604.83122991684}, {"hour": 10, "vscore": 4.475014854496835, "sscore": 42008.856192005565}, {"hour": 11, "vscore": 4.449355201432976, "sscore": 40234.6533377194}, {"hour": 12, "vscore": 4.479651286256149, "sscore": 42297.87576207919}, {"hour": 13, "vscore": 4.532114009807487, "sscore": 42846.236555682415}, {"hour": 14, "vscore": 4.521175500387353, "sscore": 41932.90288440584}, {"hour": 15, "vscore": 4.462502028191485, "sscore": 41718.30395828536}, {"hour": 16, "vscore": 4.46901281686112, "sscore": 41710.48122672351}, {"hour": 17, "vscore": 4.5388217291954, "sscore": 40768.24927687489}, {"hour": 18, "vscore": 4.5271592249042865, "sscore": 41346.4872610591}, {"hour": 19, "vscore": 4.525012398546656, "sscore": 40461.46407886699}, {"hour": 20, "vscore": 4.4785954581843335, "sscore": 38842.93096854251}, {"hour": 21, "vscore": 4.300929936708735, "sscore": 36595.34193318566}, {"hour": 22, "vscore": 4.157413373148136, "sscore": 34567.45808410202}, {"hour": 23, "vscore": 4.097682551344804, "sscore": 32583.34061363281}],
        "totale_vscore": 4.116637599367636,
        "totale_sscore": 37011.89694171986,
        "pop": 2228858.085428001
    }]
    .roma{
      fill:none;
      stroke:red;
    }
    .milan{
      fill:none;
      stroke:blue;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
    
    <div id="dailyChart"></div>

    【讨论】:

    • 你看过数据了吗,roma的最大值是5.5,你用不同的yScales画线,不是很正确。 correct image
    猜你喜欢
    • 1970-01-01
    • 2012-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多