Haritalar için D3 --- hangi aşamada coğrafi olarak veri getirmek için?


12

D3, la la ile görüntülemek için bir dünya choropleth eşlemek istiyorum:

ISO-alfa-3 tuşlarına anahtarlanmış bir veri kümem var. Yani...

danger.csv
iso,level
AFG,100
ALB,0
DZA,12

vb.

Topojson'daki talimatları izleyerek yapabileceğimi biliyorum ...

wget "http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/50m/cultural/ne_50m_admin_0_countries.zip"
unzip ne_50m_admin_0_countries.zip
ogr2ogr -f "GeoJSON" output_features.json ne_50m_admin_0_countries.shp -select iso_a3
topojson -o topo.json output_features.json --id-property iso_a3

ISO3'ün tanıdığı bir dünya haritası json'u üretmek için.

Sorum şu: İş akışının hangi noktasında danger.csv'deki verileri coğrafi verilerle birleştirmeliyim? Daha önce bir GUI olarak qGIS ile çalışmıştım, ancak birleşme nerede / olmalı / birleştirilmeli? .Shp'de mi? Ogr2ogr sonra? Topojson küçüldükten sonra tarayıcıda dinamik olarak (burada olduğu gibi http://bl.ocks.org/mbostock/4060606 http://bl.ocks.org/mbostock/3306362 )?

Python ile oldukça iyiyim, ancak javascript için oldukça yeniyim ve kendimi Bostock örneklerini kopyalayıp yapıştırarak orada üretken bir kodlayıcı olmaktan daha fazla buluyorum.

(Ayrıca buraya taşınmam gereken Stackoverflow ile ilgili, ancak daha ilgili bir takibim var: /programming/18604877/how-to-do-time-data-in-d3-maps )


Sadece @ mbostock örneklerine bakıyordum ve özellikle GeoJoins veya "CSV veya TSV dosyasında harici özelliklere sahip bir GeoJSON dosyasını birleştirmek için basit bir komut dosyası; TopoJSON çıkarıldı" olduğunu gördüm .
RyanKDalton

Yanıtlar:


11

Kendinize iki soru sorun:

  1. Coğrafyayı birden çok veri kümesinde yeniden kullanacak mısınız?

    Aynı coğrafyayı birden çok veri kümesiyle kullanacaksanız, coğrafya ve verileri ayrı tutmak ve istemcide onlara katılmak mantıklıdır. Örneklerimin çoğunda bu nedenle ayrı CSV (veya TSV) dosyaları var. Bu şekilde, her eyalet için ayrı TopoJSON oluşturmak yerine ABD eyaletleri ve ilçeleri veya benzer şekilde dünya ülkeleri için TopoJSON yeniden kullanılabilir.

    Öte yandan, bu coğrafyayı yalnızca bir kez kullanırsanız , yalnızca kodu basitleştirmek için verileri coğrafyaya "özellik olarak" eklemelisiniz. Bu yaklaşım daha basittir, çünkü yalnızca tek bir dosya yüklemeniz gerekir (bu nedenle queue.js olmaz ) ve veriler her özelliğin özellikleri olarak depolandığından, istemcideki verilere katılmanız gerekmez (bu nedenle d3 olmaz). haritası ).

    Yan not: TSV ve CSV, özelliklerin depolanmasında genellikle GeoJSON ve TopoJSON'dan çok daha verimlidir, çünkü ikincisi özellik adlarını her nesnede tekrar etmelidir. Dosya boyutu, verilerinizi ayrı bir dosyada saklamanın ve istemciye katılmanın başka bir nedeni olabilir.

  2. Verileriniz zaten coğrafyaya bağlı mı (ör. Şekil dosyanızın bir özelliği)?

    İlk soruya “hayır” yanıtı verdiğinizi ve verileri (istemcide yapmak yerine) coğrafyaya dönüştürmek istediğinizi varsayarsak, bunu nasıl yapacağınız verilerin biçimine bağlıdır.

    Verileriniz zaten şekil dosyanızın bir özelliğiyse, topojson -phangi özelliklerin oluşturulan TopoJSON dosyasına kaydedileceğini denetlemek için kullanın . Bunu, özellikleri yeniden adlandırmak ve sayılara zorlamak için de kullanabilirsiniz. Örnekler için Harita Yapalım bölümüne bakınız .

    Verileriniz ayrı bir CSV veya TSV dosyasındaysa, coğrafi özelliklerinize katılabilecek bir harici özellikler dosyası belirtmek için topojson -e'yi (ek olarak -p) kullanın . Eğer böyle bir TSV dosyanız varsa, wiki'den örnek alma:

    FIPS    rate
    1001    .097
    1003    .091
    1005    .134
    1007    .121
    1009    .099
    1011    .164
    1013    .167
    1015    .108
    1017    .186
    1019    .118
    1021    .099

    -eBunu kullanarak , bunları "işsizlik" adlı sayısal bir çıktı özelliğiyle eşleyebilirsiniz:

    topojson \
      -o output.json \
      -e unemployment.tsv \
      --id-property=+FIPS \
      -p unemployment=+rate \
      -- input.shp

    Bu yaklaşımın bir örneği Kentucky nüfus choropleth, bl.ocks.org/5144735 .


2
Ve burada gis.stackexchange yerine stackoverflow yerine sabit D3 haritalama sorularımı soruyordum çünkü orada daha fazla uzmanlık olduğunu düşündüm --- ve sonra usta burada sorumu cevaplıyor. =) Bugün öğrendiğim 2 şey var. Teşekkürler!
Mittenchops

3

İyi soru. Verdiğiniz örneklerden biri hile yapıyor gibi görünüyor, ancak takip edilmesi zor.

Örnekte iki dış veri dosyası olduğunu göreceksiniz: us.json ve unemployment.tsv . Unemployment.tsv dosyasını danger.csv gibi düşünebilirsiniz; us.json, danger.csv'den parametreleri ilişkilendirmek istediğiniz coğrafi özelliklerdir. İkincisi, unemployment.tsv sahiptir idve ratealanları idaynıdır idus.json içinde.

En azından bu örnekle, verilerinizi ve özelliklerinizi birleştirmeniz D3 istemcisindedir . Öyle istemci işsizlik oranı bu örnekte, kullanarak, ilçe özelliklerine birleştirildiği d3.map () fonksiyonu. Burası başlatıldığı yerdir:

var rateById = d3.map();

Ve işte burada rateharitalandırılıyor id:

queue()
    .defer(d3.json, "/mbostock/raw/4090846/us.json")
    .defer(d3.tsv, "unemployment.tsv", function(d) { rateById.set(d.id, +d.rate); })
    .await(ready);

İtiraf etmeliyim ki ne queue()için olduğunu bilmiyorum , ama bu tartışma için önemli değil. Ne nota önemli olduğudur her ilçe özelliği saha işsizlik ile değiştirilir . Paylaşılan tanımlayıcı ile hemen erişilebilen ( DÜZENLEME: @ olarak blord-Castillo noktaları üzerinden, bu aslında yeni birleştirici dizisi, ya da anahtar karma, üretilmesidir eşleştirilir ). Semboloji amacıyla çağrıldığı yer burasıdır (burada, her bir kantil için önceden tanımlanmış CSS sınıfları mevcuttur):idraterateidrateidrate

...
.enter().append("path")
  .attr("class", function(d) { return quantize(rateById.get(d.id)); })
  .attr("d", path);

Nerede quantize()fonksiyon tarzı için kullanılması gereken CSS sınıfının adını döndüren şimdi özelliğin tanımlanır onun işsizlik oranına göre özelliği (ilçe) idalanında.



kuyruk, seri yükleme yerine veri kaynaklarının zaman uyumsuz paralel yüklenmesine izin verir.
blord-castillo

1
Bu örnekte olup biten şey, rateById'in önemli bir karması olmasıdır. Ülke özelliklerinde hiçbir değişiklik yapılmaz ve us.json verilerine dokunulmaz. Bunun yerine, unemployment.tsv, 'rateById' adlı bir anahtar karmasına dönüştürülür. rateById.set (), unemployment.tsv dosyasındaki (us.json'da değil) her kimlik için bir anahtar eklenecek ve bu anahtarın değeri, unemployment.tsv dosyasındaki o kimliğe ilişkin ücret alanına ayarlanacak şekilde unemployment.tsv üzerinden çevrilir. . Daha sonra rateById.get () yöntemi, işsizlik oranını kimliğe göre aramak için karmayı kullanmak üzere çağrılır; bu değer, us.json özelliklerindeki stili ayarlamak için kullanılır, ardından atılır.
blord-castillo

Bu / replace / ID neden başka bir yere öznitelik olarak eklemek yerine oranla? Bu, daha sonra seçim yapmayı zorlaştırıyor gibi görünüyor.
Mittenchops

1
Kimliği oranla değiştirmez. Kimlikten orana bir arama karması oluşturur.
blord-castillo

2

İlk önce, csv'nizin ilk satırı, bu yöntemi kullanabilmek için virgülle ayrılmış sütun adlarının bir listesi olmalıdır. Bu mümkün değilse, bu konuda bir yorum ekleyin ve d3.csv.parseRowsbunun yerine nasıl kullanılacağını çözebilir miyim göreceğim d3.csv.parse. d3.csv.parsedeğerlendirici işlevi tarafından çağrılır .defer(function, url, assessor).

Dosyanızın şimdi şöyle göründüğünü varsayacağım:

danger.csv
iso,level
AFG,100
ALB,0
DZA,12
...

Bunu kullanarak ISO3'ten tehlike düzeyine kadar bir arama karması oluşturabilirsiniz.

var dangerByISO3 = d3.map();
queue()
    .defer(d3.json, "url to topo.json")
    .defer(d3.csv, "url to danger.csv", function(d) {dangerByISO3.set(d.iso, +d.level);})
    .await(ready);
function ready(error, world) {
    //You now have world as your available topojson
    //And you have dangerByISO3 as your danger level hash
    //You can lookup a danger level by dangerByISO3.get(ISO3 code)
}

Kod kılavuzu

var dangerByISO3 = d3.map();

Önce anahtar karmanız olarak işlev görecek bir d3.map () nesnesi oluşturun ve bunu dangerByISO3 değişkeninde saklayın.

queue()

Paralel yükleme için kuyruk kullanın.

.defer(d3.json, "url to topo.json")

Topojson'unuzu await fonksiyonuna iletilecek ilk argüman olarak yükleyin (hatadan sonra). Burada zincirleme bir fonksiyonun bulunduğu queue(), ancak ayrı bir satırda listelenen (sonlandırıcı noktalı virgül yoktur queue()) buradaki stile dikkat edin .

.defer(d3.csv, "url to danger.csv", function(d) {dangerByISO3.set(d.iso, +d.level);})

Burada iki şey oluyor. İlk olarak, bekleme işlevine iletilecek ikinci argümanınız olarak danger.csv'yi yüklüyorsunuz. Aşağıda göreceğiniz gibi, bu argüman aslında kullanılmamaktadır. Bunun yerine, d3.csv yükleme işlevine bir değerlendirici argümanı sağlanır. Bu değerlendirici csv'nin her bir satırını işleyecektir. Bu durumda, set fonksiyonunu dangerByISO3 olarak adlandırırız, böylece bir isoanahtarın her kombinasyonu için level, o anahtarla kullanılacak değeri ayarladık . +d.levelNotasyonu tekli kullanan +bir sayıya d.level değerini zorlamak için.

.await(ready);

Her iki veri kaynağı yüklendikten sonra, bunlar işleve iki ayrı argüman olarak iletilir ready(). Geri aramanın ilk argümanı her zaman meydana gelen ilk hatadır. Hata oluşmazsa, ilk argüman olarak null değeri iletilir. İkinci argüman birinci veri kaynağıdır (ilk görevin sonucu) ve üçüncü argüman ikinci veri kaynağıdır (ikinci görevin sonucu).

function ready(error, world) {...}

Bu geri arama işlevidir ready(). İlk errorolarak, iki yükleme görevi başarıyla tamamlanırsa null olması gerektiği argümanını alırız (hataları yakalamak ve işlemek için dil eklemeniz gerekir). Sonra topojson verilerini nesne olarak alıyoruz countries. Bu veriler, işlev gövdesinde benzer bir şeyle işlenmelidir .data(topojson.feature(world,world.objects.countries).features). Yana ready()üçüncü bir argüman almaz, ikinci görev, bizim csv sonucu, basitçe atılır. Sadece anahtar karmasını oluşturmak için kullandık ve bundan sonra ihtiyacımız yoktu.


Evet, haklısın, csv'm aslında yayınladığım dikkatsiz demo yerine iyi biçimlendirilmiş bir csv gibi görünüyor. =) Üzgünüm, güncelleyeceğim.
Mittenchops
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.