javascript - 如何使用d3,javascript和json文件将 map 划分为邮政编码?

标签 javascript d3.js maps geojson topojson

我正在尝试创建一个邮政编码区域的nyc map ,我可以根据普查数据对区域进行着色(例如,如果区域多数为白色,则区域为红色;如果区域多数为白色,则区域为蓝色)。我只是使用从此处在线找到的形状文件之一(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);
});

输出:

enter image description here

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

另外,我应该在此步骤中还是在创建路径后给路径创建的区域上色?

最佳答案

此答案使用d3 v3,并考虑人口普查区域而不是邮政编码(反射(reflect)了原始编辑,但原理保持不变)

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

I understand I am trying to "Select All" of the some sort of feature array from the json file I am using in order to create paths.



而不是从json文件中选择内容,而是在DOM中选择元素。 D3将json中的数据绑定(bind)到它们所存在的要素,在不存在的要素上生成enter()选择,在相对于json数据选择了过多DOM元素的地方生成exit()选择。

这就是为什么通常在使用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);

如果您要更新数据-例如在 map 中逐年显示某些属性,则在地理要素数量恒定的情况下(不需要),不需要.enter(),只需设置数据然后修改属性。如果新数据数组中的元素数与旧数据数组中的元素数相同,则enter()选择实际上将为空。

此方法的初始附加通常假定selectAll语句为空,因此数据中的所有项目都附加回车选择,这使许多人感到非常悲伤(a)(b)(c)(d)(e )(f)。

使用替代方法时:
svg.append('path')
  .datum(subunits)
  .attr('d',path')

您只需追加一个包含所有功能的路径元素,就无法对单个区域进行样式设置。相反,顶级方法为json中的每个元素附加一个路径。

设置 map 属性:

您可能很难将每个路径的类设置为d.coordinates。使用topojson.feature(data, data.objects.features).features从您的topojson返回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);

使用这个我得到:

enter image description here

(block)

但是,让我们在上面的内联函数(.attr('fill',function(d,i) { console.log(d); return color(i); }))中查看d。这是一个geojson对象:
Object { type: "Feature", properties: Object, geometry: Object }

如果您没有看到任何属性(它将始终具有properties属性,但是它可能为空或仅包含方法),那么您会遇到一些坏消息,这些属性为空。因此,没有包含可显示数据的属性-例如,给 map 着色。数据中也没有标识符。这使得不可能将外部数据连接到每个功能,并且该功能中没有数据可显示。 Topojson不会压缩属性,因此如果文件的文本中存在属性,则应该可以看到它们:
..."Polygon","properties":{"CTLabel":"1223","BoroCode":"4","BoroName":"Queens","CT2010":"...

显示地理特征的属性

您需要找到具有属性的地理数据集。缺少属性的功能可能对背景很有用,但对其他所有功能都没用。

我找到了2010年人口普查表here的来源。我下载了shapefile并将其转换为mapshaper.org的topojson(请确保将所有文件复制到窗口中-拖放-以便传输数据和投影数据)。数据已经被投影(到纽约州飞机),因此您应该通过在控制台中键入proj wgs84将数据取消投影/“投影”到WGS84。此answer可能有助于理解投影/非投影数据和d3

我正在使用的file具有BoroCode属性,我将使用该属性在choropleth类型显示中显示:
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);

这给了我:

enter image description here

(block)

将数据连接到要素

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

实际上,有一个很好的例子here,尽管更好的解释可能是here。我将使用可与普查区标识符(相对快速,免费)找到的少数files之一。普查信息通常很棒,因为它包含标准化的标识符。此文件是包含可支配收入数据的csv。

现在,有了共享标识符,我们可以显示地理形状并根据csv中的收入值为其分配颜色。

加载完两个文件后,我将创建一个字典:
var lookup = {};
income.forEach(function(d) { lookup[d.tractID] = +d.disposable_income; });

然后我将展示与上面几乎相同的功能:
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);

我在修改Excel中的csv并丢失了csv中的前导零时使用了parseIntparseInt从我的geojson标识符中删除了前导零。

最终结果如下所示:

enter image description here

(block)

如果看一下该块,您会看到我将d3.csv嵌套在d3.json回调函数中。这些中的每一个都是异步的,因此除非我们使用queue.js之类的库,否则我们需要等到json加载后再加载csv。这种嵌套方法解决了在加载csv之前可能对功能进行样式设置的问题

这应该涵盖如何根据geo / topo json中的增量,属性和/或通过将非空间源中的数据连接到空间形状来为 map 着色。请参见有关实现色标的块,如果没有正确的色标,color(i)将不返回任何内容。

关于javascript - 如何使用d3,javascript和json文件将 map 划分为邮政编码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42616525/

相关文章:

javascript - 如何设置第三方 cookie

javascript - 使用 D3.js 创建矩形图表

javascript - 使用 d3.entries 键值对绘制多折线图

maps - 最初在此处添加的android.view.WindowLeaked : Activity has leaked window android.小部件.ZoomButtonsController $ Container

android - 在当前主题中找不到样式 'mapViewStyle'

javascript - 使用 EmberJS 将版本添加到应用程序文件

javascript - jQuery:我该如何改进这段代码?

Azure Maps 路线方向 - 错误请求

javascript - 如何在 Highcharts 中定位 Axis 标签

javascript - 当任何列被称为 "value"时是否可以创建树形图