簡體   English   中英

Javascript d3 餅圖不會從帶有字典列表的 JSON 文件中提取數據

[英]Javascript d3 pie chart doesn't pull data from JSON file with list of dictionaries

我有一個包含數據的 .json 文件,我想從中制作一個 d3 甜甜圈(餅圖)圖。 我對 javascript 不是特別流利,我能找到的每個例子要么是從內聯 json 數據中提取的,要么是 json 文件的結構與我的不同(我的是一個字典列表;他們的通常是單個字典)。 我已經進行了幾天的故障排除,但不知何故無法解決任何實際有效的問題。 任何想法/提示?

https://www.d3-graph-gallery.com/graph/donut_label.html 上的示例使用內聯 json 數據來呈現帶有標簽的圓環圖。 我試圖通過以下方式修改它的代碼:

  • 從 /data/all-facet-digitized.json 中提取 json 數據
  • pull 標記每個字典的“facet”鍵(“true”和“false”),以及來自每個字典的“count”鍵(373977 和 55433)的值。
  • 更改色標域以匹配刻面鍵(“true”和“false”)

/data/all-facet-digitized.json 看起來像:

[
  {
    "count": "55433",
    "facet": "true"
  },  
  {
    "count": "373977",
    "facet": "false"
  }
]

我的 html 文件中的代碼如下所示:


    <div id="chart"></div> <!-- div containing the donut chart -->


    <script src="//d3js.org/d3.v4.min.js"></script>


    <script>
    // set the dimensions and margins of the graph
    var width = 450
        height = 450
        margin = 40

    // The radius of the pieplot is half the width or half the height (smallest one) minus margin.
    var radius = Math.min(width, height) / 2 - margin

    // append the svg object to the div called 'chart'
    var svg = d3.select("#chart")
      .append("svg")
        .attr("width", width)
        .attr("height", height)
      .append("g")
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");


    // Parse the Data
    d3.json("/data/all-facet-digitized.json", function(data) {

      // set the color scale
      var color = d3.scaleOrdinal()
        .domain(["true","false"])
        .range(d3.schemeDark2);

      // Compute the position of each group on the pie:
      var pie = d3.pie()
        .sort(null) // Do not sort group by size
        .value(function(d) {return d.count; })
      var data_ready = pie(d3.entries(data))

      // The arc generator
      var arc = d3.arc()
        .innerRadius(radius * 0.5)         // This is the size of the donut hole
        .outerRadius(radius * 0.8)

      // Another arc that won't be drawn. Just for labels positioning
      var outerArc = d3.arc()
        .innerRadius(radius * 0.9)
        .outerRadius(radius * 0.9)

      // Build the pie chart: Basically, each part of the pie is a path that we build using the arc function.
      svg
        .selectAll('allSlices')
        .data(data_ready)
        .enter()
        .append('path')
        .attr('d', arc)
        .attr('fill', function(d){ return(color(d.facet)) })
        .attr("stroke", "white")
        .style("stroke-width", "2px")
        .style("opacity", 0.7)

      // Add the polylines between chart and labels:
      svg
        .selectAll('allPolylines')
        .data(data_ready)
        .enter()
        .append('polyline')
          .attr("stroke", "black")
          .style("fill", "none")
          .attr("stroke-width", 1)
          .attr('points', function(d) {
            var posA = arc.centroid(d) // line insertion in the slice
            var posB = outerArc.centroid(d) // line break: we use the other arc generator that has been built only for that
            var posC = outerArc.centroid(d); // Label position = almost the same as posB
            var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2 // we need the angle to see if the X position will be at the extreme right or extreme left
            posC[0] = radius * 0.95 * (midangle < Math.PI ? 1 : -1); // multiply by 1 or -1 to put it on the right or on the left
            return [posA, posB, posC]
          })

      // Add the polylines between chart and labels:
      svg
        .selectAll('allLabels')
        .data(data_ready)
        .enter()
        .append('text')
          .text( function(d) { console.log(d.facet) ; return d.facet} )
          .attr('transform', function(d) {
              var pos = outerArc.centroid(d);
              var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2
              pos[0] = radius * 0.99 * (midangle < Math.PI ? 1 : -1);
              return 'translate(' + pos + ')';
          })
          .style('text-anchor', function(d) {
              var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2
              return (midangle < Math.PI ? 'start' : 'end')
          })
      })

    </script>

我的結果呈現為一個空白空間:


    <div id="chart">
      <svg width="450" height="450">
        <g transform="translate(225,225)"></g>
      </svg>
    </div>

schemeDark2在 d3 v4 中不存在。 我已經用schemeCategory10替換了它:

  var color = d3.scaleOrdinal()
    .domain(["true","false"])
    .range(d3.schemeCategory10);

由於您有一組對象,因此不需要d3.entries 這需要一個對象並將其轉換為一個數組,其中每個鍵都是數組的一個項目。 但是因為這里已經有一個數組,你可以直接把它放在pie()

  // Compute the position of each group on the pie:
  var pie = d3.pie()
    .sort(null) // Do not sort group by size
    .value(function(d) {return d.count; })
  var data_ready = pie(data)

現在您已經獲得了數據,您可以在任何函數上訪問它:嘗試放入console.log(data_ready)以查看可用的內容。 您將看到數據作為.data屬性綁定到每個對象。 pie()接受一個數組並將其放入便於制作餅圖的格式中。

假設我們要訪問 facet 屬性:我們將其作為item.data.facet訪問。 因此,在您的功能中,要訪問,您可以執行以下操作:

  svg
    .selectAll('allSlices')
    .data(data_ready)
    .enter()
    .append('path')
    .attr('d', arc)
    .attr('fill', function(d){ return(color(d.data.facet)) })

 <head></head> <div id="chart"></div> <!-- div containing the donut chart --> <script src="//d3js.org/d3.v4.min.js"></script> <script> // set the dimensions and margins of the graph var width = 450 height = 450 margin = 40 // The radius of the pieplot is half the width or half the height (smallest one) minus margin. var radius = Math.min(width, height) / 2 - margin // append the svg object to the div called 'chart' var svg = d3.select("#chart") .append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); // Parse the Data var data = [ { "count": "55433", "facet": "true" }, { "count": "373977", "facet": "false" } ] // set the color scale var color = d3.scaleOrdinal() .domain(["true","false"]) .range(d3.schemeCategory10); // Compute the position of each group on the pie: var pie = d3.pie() .sort(null) // Do not sort group by size .value(function(d) {return d.count; }) var data_ready = pie(data) console.log('data_r', data_ready) // The arc generator var arc = d3.arc() .innerRadius(radius * 0.5) // This is the size of the donut hole .outerRadius(radius * 0.8) // Another arc that won't be drawn. Just for labels positioning var outerArc = d3.arc() .innerRadius(radius * 0.9) .outerRadius(radius * 0.9) // Build the pie chart: Basically, each part of the pie is a path that we build using the arc function. svg .selectAll('allSlices') .data(data_ready) .enter() .append('path') .attr('d', arc) .attr('fill', function(d){ return(color(d.data.facet)) }) .attr("stroke", "white") .style("stroke-width", "2px") .style("opacity", 0.7) // Add the polylines between chart and labels: svg .selectAll('allPolylines') .data(data_ready) .enter() .append('polyline') .attr("stroke", "black") .style("fill", "none") .attr("stroke-width", 1) .attr('points', function(d) { var posA = arc.centroid(d) // line insertion in the slice var posB = outerArc.centroid(d) // line break: we use the other arc generator that has been built only for that var posC = outerArc.centroid(d); // Label position = almost the same as posB var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2 // we need the angle to see if the X position will be at the extreme right or extreme left posC[0] = radius * 0.95 * (midangle < Math.PI ? 1 : -1); // multiply by 1 or -1 to put it on the right or on the left return [posA, posB, posC] }) // Add the polylines between chart and labels: svg .selectAll('allLabels') .data(data_ready) .enter() .append('text') .text( function(d) { return d.data.facet} ) .attr('transform', function(d) { var pos = outerArc.centroid(d); var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2 pos[0] = radius * 0.99 * (midangle < Math.PI ? 1 : -1); return 'translate(' + pos + ')'; }) .style('text-anchor', function(d) { var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2 return (midangle < Math.PI ? 'start' : 'end') }) </script>

好的,這里的問題是您完全錯過了轉換 JSON 響應后data_ready的結構。 您可能希望在設置data_ready后添加console.log(data_ready)並在控制台中檢查它以更好地理解以下修復。

首先是顏色修復:

       .attr('fill', function(d){ return(color(d.data.value.facet)) })

然后是數據修復:

       .value(function(d) {return d.value.count; })

最后是標簽修復:

       .text( function(d) { console.log(d.data.key) ; return d.data.value.facet } )

您的腳本應如下所示:

// set the dimensions and margins of the graph
var width = 450
    height = 450
    margin = 40

// The radius of the pieplot is half the width or half the height (smallest one). I subtract a bit of margin.
var radius = Math.min(width, height) / 2 - margin

// append the svg object to the div called 'my_dataviz'
var svg = d3.select("#chart")
  .append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

d3.json("/data/all-facet-digitized.json", function(data) {

// set the color scale
var color = d3.scaleOrdinal()
  .domain(["true","false"])
  .range(d3.schemeDark2);

// Compute the position of each group on the pie:
var pie = d3.pie()
  .sort(null) // Do not sort group by size
  .value(function(d) {return d.value.count; })
var data_ready = pie(d3.entries(data))

// The arc generator
var arc = d3.arc()
  .innerRadius(radius * 0.5)         // This is the size of the donut hole
  .outerRadius(radius * 0.8)

// Another arc that won't be drawn. Just for labels positioning
var outerArc = d3.arc()
  .innerRadius(radius * 0.9)
  .outerRadius(radius * 0.9)

// Build the pie chart: Basically, each part of the pie is a path that we build using the arc function.
svg
  .selectAll('allSlices')
  .data(data_ready)
  .enter()
  .append('path')
  .attr('d', arc)
  .attr('fill', function(d){ return(color(d.data.value.facet)) })
  .attr("stroke", "white")
  .style("stroke-width", "2px")
  .style("opacity", 0.7)

// Add the polylines between chart and labels:
svg
  .selectAll('allPolylines')
  .data(data_ready)
  .enter()
  .append('polyline')
    .attr("stroke", "black")
    .style("fill", "none")
    .attr("stroke-width", 1)
    .attr('points', function(d) {
      var posA = arc.centroid(d) // line insertion in the slice
      var posB = outerArc.centroid(d) // line break: we use the other arc generator that has been built only for that
      var posC = outerArc.centroid(d); // Label position = almost the same as posB
      var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2 // we need the angle to see if the X position will be at the extreme right or extreme left
      posC[0] = radius * 0.95 * (midangle < Math.PI ? 1 : -1); // multiply by 1 or -1 to put it on the right or on the left
      return [posA, posB, posC]
    })

// Add the polylines between chart and labels:
svg
  .selectAll('allLabels')
  .data(data_ready)
  .enter()
  .append('text')
    .text( function(d) { console.log(d.data.key) ; return d.data.value.facet } )
    .attr('transform', function(d) {
        var pos = outerArc.centroid(d);
        var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2
        pos[0] = radius * 0.99 * (midangle < Math.PI ? 1 : -1);
        return 'translate(' + pos + ')';
    })
    .style('text-anchor', function(d) {
        var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2
        return (midangle < Math.PI ? 'start' : 'end')
    })
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM