지도 용 D3-- 지리로 데이터를 가져 오는 단계는 무엇입니까?


12

D3, la로 표시하기 위해 세계 choropleth를 매핑하고 싶습니다.

ISO-alpha-3 키를 사용하여 표시하려는 데이터 세트가 있습니다. 그래서...

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

기타

topojson의 지침에 따라 할 수있는 것을 알고 있습니다.

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에 의해 ID가 지정된 월드 맵 JSON을 생성합니다.

내 질문은 : 워크 플로우의 어떤 시점에서 danger.csv의 데이터를 지리 데이터로 병합해야합니까? 이전에 qGIS를 GUI로 사용해 왔지만 / should / 병합은 어디서 발생합니까? .shp? ogr2ogr 후? topojson 축소 후 브라우저에서 동적으로 (예 : http://bl.ocks.org/mbostock/4060606 http://bl.ocks.org/mbostock/3306362 )?

나는 파이썬에 꽤 익숙하지만 자바 스크립트에 익숙하지 않고 실제로 Bostock 예제를 복사하여 붙여 넣는 것보다 실제로 생성 코더가되는 것을 발견했습니다.

(: 나는 또한 어쩌면 내가 여기에 이전해야한다는 유래에 관련,하지만 더 복잡 후속이 /programming/18604877/how-to-do-time-data-in-d3-maps )


방금 @mbostock의 예제를보고 GeoJoins 또는 "GeoJSON 파일을 CSV 또는 TSV 파일의 외부 속성과 결합하기위한 간단한 스크립트; TopoJSON에서 추출한 간단한 스크립트"가 있습니다.
RyanKDalton

답변:


11

두 가지 질문을 해보십시오.

  1. 여러 데이터 세트에서 지리를 재사용 하시겠습니까?

    여러 데이터 세트에 동일한 지리를 사용하는 경우 지리와 데이터를 별도로 유지하고 클라이언트에서 결합하는 것이 좋습니다. 많은 예제에는 이러한 이유로 별도의 CSV (또는 TSV) 파일이 있습니다. 이런 식으로, 모든 예제에 대해 별도의 TopoJSON을 작성하는 대신 미국 주 및 카운티 또는 이와 유사한 세계 국가 의 TopoJSON을 재사용 할 수 있습니다.

    반면에이 지리를 한 번만 사용 하는 경우 코드를 단순화하기 위해 데이터를 지리에 속성으로 "베이크"해야합니다. 이 접근 방식은 단일 파일 만로드하면되므로 ( queue.js 는 필요하지 않음 ) 데이터가 각 기능의 특성으로 저장되므로 클라이언트에서 데이터를 결합 할 필요가 없으므로 ( d3 없음) 지도 ).

    참고 : TSV 및 CSV는 GeoJSON 및 TopoJSON보다 속성을 저장하는 데 종종 훨씬 효율적입니다. 왜냐하면 후자는 모든 객체에서 속성 이름을 반복해야하기 때문입니다. 파일 크기는 데이터를 별도의 파일에 저장하고 클라이언트에서 결합하는 또 다른 이유 일 수 있습니다.

  2. 데이터가 이미 지리에 바인딩되어 있습니까 (예 : shapefile의 속성)?

    첫 번째 질문에 "아니오"라고 대답하고 데이터를 클라이언트에서 수행하지 않고 지리에 굽고 싶다고 가정 할 경우, 데이터 형식에 따라 방법이 달라집니다.

    데이터가 이미 shapefile의 속성 인 topojson -p경우 생성 된 TopoJSON 파일에 저장할 속성을 제어하는 ​​데 사용 하십시오. 이 속성을 사용하여 속성의 이름을 바꾸고 숫자로 강제 변환 할 수도 있습니다. 참조 하자 만들기지도 의 예를 들어.

    데이터가 별도의 CSV 또는 TSV 파일 인 경우 topojson -e (외에 추가 -p)를 사용 하여 지리적 기능에 결합 할 수 있는 외부 속성 파일 을 지정 하십시오. 다음과 같은 TSV 파일이있는 경우 위키에서 예제를 가져옵니다.

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

    을 사용하면 -e다음과 같이 "unmployment"라는 숫자 출력 속성에 매핑 할 수 있습니다.

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

    이 접근법의 예는 Kentucky 인구 choropleth, bl.ocks.org/5144735 입니다.


2
그리고 여기에 gis.stackexchange 대신 stackoverflow에 대한 어려운 D3 매핑 질문을하고 있었는데 거기에 더 많은 전문 지식이 있다고 생각했기 때문에 마스터가 여기에 내 질문에 대답했습니다. =) 글쎄, 그것은 내가 오늘 배운 두 가지를 만듭니다. 감사!
Mittenchops

3

좋은 질문. 제공 한 예제 중 하나는 따르기가 어렵지만 트릭을 수행하는 것 같습니다.

당신은주의 것 예는 두 개의 외부 데이터 파일이 us.jsonunemployment.tsv을 . unemployment.tsv를 danger.csv처럼 생각할 수 있습니다. us.json은 danger.csv의 매개 변수를 연관시키려는 지리적 기능입니다. 후자 인 unemployment.tsv에는 us.json 과 동일한 필드 idrate필드가 있습니다.idid

최소한이 예에서는 데이터와 기능을 병합해야합니다 . 그것은 인 클라이언트의 실업률이 예에서, 사용 기능 군에 접합 d3.map () 함수. 이것이 초기화되는 곳입니다.

var rateById = d3.map();

그리고 이것은 다음에 rate매핑됩니다 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);

나는 무엇이 무엇인지 모른다는 것을 인정해야 queue()하지만,이 논의에서 중요하지는 않습니다. 주의해야 할 것은 각 카운티 기능 id필드가 실업으로 대체된다는 것 rate입니다. (가) rate공용 식별자에 의해 현재 접근 id( EDIT @ 같이 blord-카스 포인트 아웃이 실제로는 새로운 연관 배열 또는 해시 키의 세대 rate받는 매핑된다id ). 이것은이 어디 rate기호 (여기서, 미리 정의 된 CSS 클래스는 각 분위수에 사용할 수있는)의 목적을 위해 호출된다 :

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

여기서 quantize()함수는 실업률을 기준으로 해당 기능 (군)의 스타일을 지정하는 데 사용해야하는 CSS 클래스의 이름을 반환합니다.이 기능은 이제 기능의 id필드에 정의되어 있습니다.



대기열은 직렬로드 대신 데이터 소스의 비동기 병렬로드를 허용합니다.
blord-castillo

1
이 예제에서 진행중인 것은 rateById가 키 해시라는 것입니다. 국가 기능은 변경되지 않았으며 us.json 데이터는 변경되지 않았습니다. 대신 unemployment.tsv는 'rateById'라는 키 해시로 변환됩니다. rateById.set ()은 unemployment.tsv를 통해 루프되므로 unemployment.tsv (us.json이 아닌)의 각 ID에 키가 삽입되고 해당 키의 값이 unemployment.tsv의 해당 ID에 대한 비율 필드로 설정됩니다. . 나중에 rateById.get ()은 해시를 사용하여 실업률을 id로 조회하기 위해 호출됩니다. 이 값은 us.json 기능에서 스타일을 설정 한 다음 폐기하는 데 사용됩니다.
blord-castillo

왜이 ID를 다른 곳에 속성으로 첨부하지 않고 요율로 ID를 대체합니까? 나중에 선택하기가 더 어려워 보입니다.
Mittenchops

1
ID를 요율로 바꾸지 않습니다. id에서 rate까지 조회 해시를 작성합니다.
blord-castillo

2

먼저,이 방법을 사용하려면 CSV의 첫 번째 행이 쉼표로 구분 된 열 이름 목록이어야합니다. 이것이 가능하지 않으면 이것에 대한 의견을 추가하면 d3.csv.parseRows대신에 사용 방법을 알아낼 수 있는지 알 수 있습니다 d3.csv.parse. d3.csv.parse에 평가자 함수가 호출합니다 .defer(function, url, assessor).

파일이 이제 다음과 같이 가정합니다.

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

이를 사용하면 ISO3에서 위험 수준까지 조회 해시를 만들 수 있습니다.

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)
}

코드 연습

var dangerByISO3 = d3.map();

먼저 키 해시로 작동하는 d3.map () 객체를 만들고이를 dangerByISO3 변수에 저장합니다.

queue()

병렬로드에는 큐를 사용하십시오.

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

topojson을 첫 번째 인수로로드하여 await 함수에 전달하십시오 (오류 후). 이 함수가에 묶인 함수 queue()이지만 별도의 줄에 나열 되는 스타일에주의하십시오 (마침표 세미콜론은 없습니다 queue()).

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

여기서 두 가지 일이 일어나고 있습니다. 먼저, await 함수에 전달할 두 번째 인수로 danger.csv를로드하고 있습니다. 아래에서 볼 수 있듯이이 인수는 실제로 사용되지 않습니다. 대신로드 함수 d3.csv에 평가자 인수가 제공됩니다. 이 평가자는 CSV의 각 행을 처리합니다. 이 경우, 우리는 dangerByISO3에서 set 함수를 호출하여 iso키 의 각 조합에 대해 level해당 키와 함께 사용할 값을 설정합니다 . 이 +d.level표기법은 단항 +을 사용 하여 d.level의 값을 숫자로 강제합니다.

.await(ready);

두 데이터 소스가 모두로드되면 함수에 별도의 두 인수로 전달됩니다 ready(). 콜백에 대한 첫 번째 인수는 항상 발생한 첫 번째 오류입니다. 오류가 발생하지 않으면 첫 번째 인수로 null이 전달됩니다. 두 번째 인수는 첫 번째 데이터 소스 (첫 번째 작업의 결과)이고 세 번째 인수는 두 번째 데이터 소스 (두 번째 작업의 결과)입니다.

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

이것은 콜백 함수 ready()입니다. 먼저 error두 개의로드 작업이 성공적으로 완료되면 널 (null)이어야한다는 인수를 취합니다 (실제로 오류를 포착하고 처리 할 언어를 추가해야 함). 다음으로 topojson 데이터를 객체로 사용합니다 countries. 이 데이터는 다음과 같이 함수 본문에서 처리해야합니다 .data(topojson.feature(world,world.objects.countries).features). ready()세 번째 인수를 취하지 않기 때문에 두 번째 작업 인 csv의 결과는 단순히 폐기됩니다. 우리는 키 해시를 빌드하는 데만 사용했으며 그 후에는 필요하지 않았습니다.


그래, 맞아 내 csv는 실제로 게시 한 부주의 한 데모 대신 잘 구성된 csv처럼 보입니다. =) 죄송합니다. 업데이트하겠습니다.
Mittenchops
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.