用JSON替换D3.js CSV源

时间:2019-02-11 03:17:44

标签: javascript d3.js

编辑:根据下面的答案,以供将来参考,原始资料由palewire World Choropleth

我试图通过将数据源从CSV切换到JSON来重用Mike的例子。

原始数据源是通过CSV文件加载的,如下所示:

// Load external data and boot
d3.queue()
    .defer(d3.json, "http://enjalot.github.io/wwsd/data/world/world-110m.geojson")
    .defer(d3.csv, "mooc-countries.csv", function(d) { data.set(d.code, +d.total); })
    .await(ready);

function ready(error, topo) {
    if (error) throw error;

    // Draw the map
    svg.append("g")
        .attr("class", "countries")
        .selectAll("path")
        .data(topo.features)
        .enter().append("path")
            .attr("fill", function (d){
                // Pull data for this country
                d.total = data.get(d.id) || 0;
                // Set the color
                return colorScale(d.total);
            })
            .attr("d", path);
}

但是我正在尝试更改第二个.defer来从JSON文件中获取数据,到目前为止,我发现它应该与此接近:

.defer(d3.json, "data.json", function(error, data) {
      data.forEach(function(d) {
          return {
               d.code,
               d.total;
             };
           });
         })

JSON源:

[
  {
    "name" : "Burkina Faso",
    "total" : 5,
    "percent" : 0.3,
    "code" : "BFA"
  },
  {
    "name" : "Democratic Republic of the Congo",
    "total" : 4,
    "percent" : 0.3,
    "code" : "COD"
  },
  {
    "name" : "Haiti",
    "total" : 8,
    "percent" : 0.3,
    "code" : "HTI"
  }
]

2 个答案:

答案 0 :(得分:1)

您未包含指向原始块的任何链接,但进行了谷歌搜索,我认为您指的是World Choropleth py浅线。将其移植为使用d3.json()需要一些额外的步骤。

  1. 有一个全局变量data,它是一个d3.map

    var data = d3.map();
    

    此词典包含从CSV提取的codetotal映射,稍后在确定fill时使用。如果要保留代码的一般结构,则需要从JSON输入中填写相同的值。这直接将我们引向下一个问题。

  2. 在原始代码中,此行的函数填充了地图:

    .defer(d3.csv, "mooc-countries.csv", function(d) { data.set(d.code, +d.total); })
    

    但是,重要的是要了解此功能不是处理接收到的数据集的回调。该回调是隐藏的,并由队列隐式提供。相反,这是行转换函数,它按CSV的每一行执行。这使用.set()将每一行放入地图。遵循D3的命名约定,该函数的参数表示为d,它引用的是单个数据而不是整个数据集。

    另一方面,

    d3.json()不具有行转换功能,因为JSON数据本质上是分层的,而不是像CSV那样基于行的。您可以将该逻辑放在传递到.await()的回调中:

    d3.queue()
      .defer(d3.json, "http://enjalot.github.io/wwsd/data/world/world-110m.geojson")
      .defer(d3.json, "data.json")   // No callback, just loading.
      .await(ready);
    
    function ready(error, topo, json) {
      if (error) throw error;
    
      var data = d3.map();   // Can be moved here, no need to pollute the global scope.
      json.forEach(function(d) { data.set(d.code, +d.total); });  // Populate the map.
      // ...business as usual
    }
    

其余代码(例如,迁移到D3 v5和ES6)仍有很大的改进空间,但是上述操作可能是最不侵入的方式,并且将使大多数原始代码保持不变。

答案 1 :(得分:0)

您可能正在寻找的是使用所选键返回一个新数组。 forEach内部的退货是当前的问题。也许您想退货

map将对象数组转换为其他格式,然后返回到延迟函数

.defer(d3.json, "data.json", function(error, data) {
      return data.map(function(d) {
          return {
               id: d.code,
               total: d.total;
             };
           });
         })