当前位置: 首页 > 知识库问答 >
问题:

JavaScriptD3饼图不会从JSON文件和字典列表中提取数据

李飞翼
2023-03-14

我有一个包含数据的.json文件,我想用它制作一个d3甜甜圈(饼图)。我对javascript不是特别精通,我能找到的每个示例要么来自内联json数据,要么json文件的结构与我的不同(我的是一个字典列表;它们通常是单个字典)。我已经排除故障几天了,但不知怎么的,我无法找到任何真正有效的方法。有什么想法/建议吗?

例如https://www.d3-graph-gallery.com/graph/donut_label.html 使用内联json数据呈现带标签的圆环图。我试图通过以下方式修改该代码:

  • 从/data/all-facet.json中提取json数据

/data/all-facet-digidated.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>

共有2个答案

寿亦
2023-03-14

好的,这里的问题是,在转换JSON响应之后,您完全忽略了如何构造data\u ready。在设置data\u ready之后,您可能需要添加console.log(data\u 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')
    })
})
梁丘扬
2023-03-14

D3V4中不存在schemeDark2。我已将其替换为schemecategory 10

  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\u 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>
 类似资料:
  • 问题内容: 我有一个字典列表,我需要从字典的给定键中获取值的列表(所有字典都具有相同的键)。 例如,我有: 我需要得到1,2,3 当然,我可以通过以下方式获得它: 但是我想找到一种更好的方法。 问题答案: 使用简单的列表推导(如果您确定每个字典都有键): 否则,您需要首先检查是否存在:

  • 问题内容: 我有这样的字典列表: 我想要 最好的方法是什么? 问题答案: 假设每个字典都有一个键,你可以编写(假设你的列表名为l) 如果value可能丢失,可以使用

  • 问题内容: 我正在尝试获取词典列表中所有键的列表,以便填写csv.DictWriter的fieldnames参数。 以前,我有这样的事情: 我当时习惯于使用列表中的第一本字典并提取其键。 现在我有了类似的东西,其中一个字典比另一个字典具有更多的key:value对(可能是任何结果)。新密钥是根据来自API的信息动态添加的,因此它们可能会或可能不会出现在每个字典中,而且我事先也不知道会有多少个新密钥

  • 我的数据框中有一列包含JSON列表,但类型是字符串。我需要在此列上运行,因此首先需要将其转换为列表。我找不到太多关于这个用例的参考。 示例数据: 上面是数据的样子,字段是不固定的(索引0可能有JSON和一些字段,而索引1将有一些字段和一些其他字段)。列表中可以有更多嵌套的JSONs或一些额外的字段。我现在正在用这个- <code>“分解(拆分(regexp_replace(regexp_repla

  • 问题内容: 是否可以从数据库而不是磁盘上的文件加载视图?它不一定必须是数据库,也可以是任何字符串。 我想我提这个问题还为时过早…我仍然期待任何答案,但是我一定会首先做更多研究。 编辑 所以我写了一个快速样本,可以满足我的要求。我会在一切正常运行时发布更新。 更新 在玩了之后,我发现了一些有趣的东西。如果我从和方法中删除,并且仅返回true,则返回的文件将被解析,并且输出将如预期的那样。(就像我放了

  • 我正在使用IBM Watson的音调分析器分析文本,并试图提取与句子音调有关的所有信息(例如,、、、、和)并将其添加到dataframe中(带有列;、