簡體   English   中英

如何使用 d3、javascript 和 json 文件將地圖划分為郵政編碼?

[英]How to divide a map into zipcodes using d3, javascript, and a json file?

我正在嘗試創建一個紐約地圖,其中包含我可以根據人口普查數據着色的郵政編碼區域(例如,如果多數為白色,則將區域着色為紅色,如果多數為非白色,則為藍色)。 我只是使用我從這里在線找到的形狀文件之一( 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);
});

輸出:

在此處輸入圖片說明

我的代碼的最后一部分(和第一部分)是在https://bost.ocks.org/mike/map/之后建模的。 我知道我正在嘗試從我正在使用的 json 文件中“全選”某種特征數組以創建路徑。 在我的數據中,有一個坐標數組,我正在嘗試訪問和使用它。 我的代碼沒有拋出任何錯誤,所以我不確定在哪里調試。

另外,我應該在此步驟中還是在創建路徑之后為路徑創建的區域着色?

這個答案使用 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);

如果您正在更新數據 - 比如說在地圖中顯示一些逐年的屬性,如果地理特征的數量是恆定的(可能是這種情況),則不需要.enter() ),您只需設置數據,然后修改屬性。 如果新數據數組中的元素數量與舊數據相同,則enter()選擇實際上將為空。

這種方法的初始追加一般假設selectAll語句為空,這樣數據中的所有項都追加了回車選擇,這讓很多人很傷心( a ) ( b ) ( c ) ( d ) ( e ) ( f )

使用替代方法時:

svg.append('path')
  .datum(subunits)
  .attr('d',path')

您只需添加一個包含所有功能的路徑元素,這使得無法對單個區域進行樣式設置。 相比之下,top 方法為 json 中的每個元素附加一個路徑。

設置地圖屬性:

您可能難以將每個路徑的類設置為d.coordinates 使用topojson.feature(data, data.objects.features).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);

使用這個我得到:

在此處輸入圖片說明

但是,讓我們看看上面的內聯函數中的 d( .attr('fill',function(d,i) { console.log(d); return color(i); }) )。 它是一個 geojson 對象:

Object { type: "Feature", properties: Object, geometry: Object }

如果你沒有看到任何屬性(它總是有一個 properties 屬性,但它可能是空的或只包含方法),你有一些壞消息,這些屬性是空的。 因此,沒有包含可以顯示的數據的屬性 - 例如為地圖着色。 數據中也沒有標識符。 這使得將外部數據連接到每個特征變得不可能,並且特征中沒有數據可顯示。 Topojson 不壓縮屬性,因此如果它們存在於文件的文本中,您應該能夠看到它們:

..."Polygon","properties":{"CTLabel":"1223","BoroCode":"4","BoroName":"Queens","CT2010":"...

顯示地理要素的屬性

您需要找到具有屬性的地理數據集。 無屬性的功能可能對背景很有用,但對其他一切用處不大。

我在這里找到了 2010 年人口普查區的來源。 我在mapshaper.org下載了 shapefile 並將其轉換為topojson (確保將所有文件復制到窗口中 - 拖放 - 以便傳輸數據和投影數據)。 數據已經投影(到紐約州平面),因此您應該通過在控制台中鍵入proj wgs84來取消投影/“投影”到 WGS84。 這個答案可能有助於理解投影/未投影數據和 d3

我正在使用的文件具有屬性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);

這給了我:

在此處輸入圖片說明

將數據連接到特征

許多 shapefile、topojson、geosjons、要素類等不包含許多屬性/屬性。 這些包含地理坐標的文件通常基於每個數據源中共享的標識符連接到數據連接中包含屬性/屬性(但沒有坐標)的文件。

在實踐中,這里有一個很好的例子,盡管這里可能有更好的解釋。 我將使用我能找到的少數文件之一(相對快速且免費),其中包含人口普查區標識符。 人口普查信息通常很好,因為它包含標准化的標識符。 該文件是一個包含可支配收入數據的 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);

我使用了parseInt因為我在 Excel 中修改了 csv 並丟失了 csv 中的前導零, parseInt從我的 geojson 標識符中刪除了前導零。

最終結果類似於:

在此處輸入圖片說明

如果您查看該塊,您會看到我將 d3.csv 嵌套在 d3.json 回調函數中。 每一個都是異步的,所以除非我們使用像 queue.js 這樣的庫,否則我們需要等到 json 加載后才能加載 csv。 這種嵌套方法解決了在加載 csv 之前可能對特征進行樣式設置的問題

這應該涵蓋如何基於增量、geo/topo json 中的屬性和/或通過將來自非空間源的數據連接到空間形狀來為地圖着色。 請參閱色標的實現塊,如果沒有適當的color(i)color(i)將不會返回任何內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM