如何使用d3,javascript和json文件将地图划分为zipcodes?

pr3*_*338 4 javascript maps geojson d3.js topojson

我正在尝试创建一个带有我可以根据人口普查数据着色的邮政编码区域的纽约地图(如果大多数为白色则为红色区域,如果为多数非白色则为蓝色区域).我只是使用我在网上找到的形状文件之一(https://data.cityofnewyork.us/Business/Zip-Code-Boundaries/i8iw-xf4u/data).

我将shp文件转换为geojson,然后转换为topojson文件.

如果有人能查看我下面的代码,我会很感激,并告诉我如何才能做到这一点.

码:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
</style>
<body>
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>

<script>

var width = 500,
    height = 500;

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

  var projection = d3.geo.albers()
   .center([0,40.7])
   .rotate([74,0])
   .translate([width/2,height/2])
   .scale(65000);

   var path = d3.geo.path()
    .projection(projection);

d3.json("zipcode.json", function(error, uk) {
    console.log(uk)
    console.log(uk.objects)
    console.log(uk.objects.zipcode)
  if (error) return console.error(error);
  var subunits = topojson.feature(uk, uk.objects.zipcode);

    svg.append("path")
        .datum(subunits)
        .attr("d", path);
});
Run Code Online (Sandbox Code Playgroud)

输出:

在此输入图像描述

我的代码的最后一部分(以及第一部分)是在https://bost.ocks.org/mike/map/之后建模的.我理解我正在尝试从我正在使用的json文件中选择某种特征数组的"全选"以创建路径.在我的数据中,有一个坐标数组,我试图访问和使用它.我的代码没有抛出任何错误,所以我不确定在哪里调试.

另外,我应该为这一步中创建的路径或创建路径后的区域着色?

And*_*eid 10

这个答案使用d3 v3并考虑人口普查区而不是邮政编码(反映原始编辑,但原则保持不变)

选择在添加功能中的作用:

我理解我正在尝试从我正在使用的json文件中选择某种特征数组的"全选"以创建路径.

您没有从json文件中选择某些内容,而是在DOM中选择元素.D3将json中的数据绑定到它们存在的特征,在它们不存在的情况下生成enter()选择,并产生exit()选择,其中选择了与json数据相关的多余DOM元素.

这就是为什么最初在selectAll(type).data(data) 声明中添加数据后会附带一个.enter()声明.enter返回必须添加到DOM的元素:

svg.selectAll(".tract")
    // bind data to the selection
    .data(topojson.feature(uk, uk.objects.nyct2010).features)
  .enter()
    // set properties for the new elements:
    .append("path") 
    .attr("class", "tract")
    .attr("d", path);
Run Code Online (Sandbox Code Playgroud)

如果您正在更新数据 - 比如在地图中显示逐年属性,则不需要.enter()如果地理要素的数量不变(可能是这种情况),您只需设置数据然后修改属性即可.如果新数据数组中的元素数与旧数据元素相同,则enter()选择实际上为空.

使用此方法的初始附加通常假定selectAll语句为空,因此数据中的所有项都附加了输入选择,这会使许多人感到很悲伤(a)(b)(c)(d)(e))(f).

使用备用方法时:

svg.append('path')
  .datum(subunits)
  .attr('d',path')
Run Code Online (Sandbox Code Playgroud)

您只需附加一个包含所有要素的路径元素,这样就无法对单个区域进行样式化.相反,top方法为json中的每个元素添加一个路径.

设置地图属性:

您可能很难设置每个路径的类d.coordinates.使用topojson.feature(data, data.objects.features).featurestopojson中的返回geojson.每个要素的坐标属性是一个数组 - 可能不适用于类声明.

但是,你有正确的方法.内联函数可以轻松设置属性:

var color = d3.scale.category20();

svg.selectAll("path")
  .data(subunits) // from the question code.
  .enter()
  .append('path')
  .attr('fill',function(d,i) { return color(i); })
  .attr("d", path);
Run Code Online (Sandbox Code Playgroud)

使用这个我得到:

在此输入图像描述

()

但是,让我们看看上面的内联函数中的d(.attr('fill',function(d,i) { console.log(d); return color(i); })).它是一个geojson对象:

Object { type: "Feature", properties: Object, geometry: Object }
Run Code Online (Sandbox Code Playgroud)

如果您没有看到任何属性(它将始终具有属性属性,但它可能为空或仅包含方法),则会有一些坏消息,属性为空.因此,没有包含可以显示的数据的属性 - 例如着色地图.数据中也没有标识符.这使得无法将外部数据连接到每个功能,并且要显示的功能中没有数据.Topojson不压缩属性,因此如果它们出现在文件的文本中,您应该能够看到它们:

..."Polygon","properties":{"CTLabel":"1223","BoroCode":"4","BoroName":"Queens","CT2010":"...
Run Code Online (Sandbox Code Playgroud)

显示地理特征的属性

您需要找到具有属性的地理数据集.无属性功能可能对背景很有用,但对其他一切功能不太有用.

我在这里找到了2010年人口普查的来源.我下载了shapefile并将其转换为mapshaper.org上的topojson(确保将所有文件复制到窗口中 - 拖放 - 以便传输数据和投影数据).数据已经预测(到纽约州飞机),因此您应该通过proj wgs84在控制台中输入来将其"投影"到"WGS84 ".这个答案可能有助于理解预计/未预测的数据和d3

我正在使用的文件具有BoroCode我将用于在等值线型显示中显示的属性:

svg.selectAll("path")
   .data(topojson.feature(data, data.objects.nyct2010).features)
   .enter()
   .append('path')
   .attr('fill',function(d) {return color(d.properties.BoroCode); })
   .attr("d", path);
Run Code Online (Sandbox Code Playgroud)

这给了我:

在此输入图像描述

()

将数据连接到功能

许多shapefile,topojsons,geosjons,要素类等不包含许多属性/属性.这些包含地理坐标的文件通常根据每个数据源中共享的标识符连接到数据连接中包含属性/属性(但没有坐标)的文件.

有一个很好的例子在这里上,在实践中,虽然一个更好的解释可能是在这里.我将使用我能找到的少数文件之一(相对快速和免费)和人口普查区标识符.人口普查信息通常很好,因为它包含标准化标识符.该文件是包含可支配收入数据的csv.

现在使用共享标识符,我们可以显示地理形状并根据csv中的收入值为它们指定颜色.

加载两个文件后,我将创建一个字典:

var lookup = {};
income.forEach(function(d) { console.log(d); lookup[d.tractID] = +d.disposable_income; });
Run Code Online (Sandbox Code Playgroud)

然后我将展示功能,几乎与上面相同:

svg.selectAll("path")
   .data(topojson.feature(data, data.objects.nyct2010).features)
   .enter()
   .append('path')
   .attr('fill',function(d) { return color(lookup[parseInt(d.properties.CT2010)] ); })
   .attr("d", path);
Run Code Online (Sandbox Code Playgroud)

我用过,parseInt因为我在Excel中修改了csv并丢失了csv中parseInt的前导零,从我的geojson标识符中删除了前导零.

最终结果如下:

在此输入图像描述

()

如果你看一下这个块,你会看到我在d3.json回调函数中嵌套了d3.csv.每个都是异步的,所以除非我们使用像queue.js这样的库,否则我们需要等到加载json之后再加载csv.这种嵌套方法解决了在加载csv之前可能为特征设置样式的问题

这应该包括如何基于增量,geo/topo json中的属性和/或通过将来自非空间源的数据连接到空间形状来为地图着色.查看用于执行色标的块,没有适当的比例color(i)将不会返回任何内容.