Javascript D3饼图不会从具有字典列表的JSON文件中提取数据

如何解决Javascript D3饼图不会从具有字典列表的JSON文件中提取数据

我有一个包含数据的.json文件,我想从中制作一个d3甜甜圈(饼图)图表。我不是特别精通javascript,每个示例我都可以发现从内嵌json数据中提取的内容或json文件的结构与我的不同(mine是字典列表;它们通常是单个字典)。我已经进行了几天的故障排除,以某种方式无法解决任何实际可行的问题。有什么想法/提示吗?

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

  • 从/data/all-facet-digitized.json中提取json数据
  • 拉标签每个词典的“ facet”键(“ true”和“ false”),以及每个词典的“ count”键的值(373977和55433)。
  • 更改色标域以匹配构面键(“ true”和“ false”)

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

$ node repro.js

logged { [Error: EROFS: read-only file system,open '/test.txt'] errno: -30,code: 'EROFS',syscall: 'open',path: '/test.txt' }

我的html文件中的代码如下:

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

我的结果呈现为空白:


    <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>

解决方法

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的结构。您可能希望在设置console.log(data_ready)之后立即添加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"," + 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,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')
    })
})

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-