Eu gostaria de mapear um coro mundial para exibição com D3, a la:
Eu tenho um conjunto de dados que eu gostaria de exibir que é codificado para chaves ISO-alfa-3. Então...
danger.csv
iso,level
AFG,100
ALB,0
DZA,12
etc.
Seguindo as instruções no topojson, eu sei que posso fazer ...
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
para produzir um json de mapa do mundo que seja identificado pela ISO3.
Minha pergunta é: em que momento do fluxo de trabalho devo mesclar os dados de danger.csv nos dados geográficos? Eu já havia trabalhado com o qGIS como uma GUI, mas onde / deve / a fusão acontecer? No .shp? Após o ogr2ogr? Dinamicamente no navegador após o topojson encolher (como aqui http://bl.ocks.org/mbostock/4060606 http://bl.ocks.org/mbostock/3306362 )?
Eu sou muito bom com python, mas muito novo em javascript, e me pego copiando e colando exemplos de Bostock mais do que realmente ser um codificador generativo lá.
(Eu também tenho um acompanhamento relacionado, mas mais envolvido, ao Stackoverflow, que talvez eu deva migrar aqui: /programming/18604877/how-to-do-time-data-in-d3-maps )
Respostas:
Faça a si mesmo duas perguntas:
Você vai reutilizar a geografia em vários conjuntos de dados?
Se você usar a mesma região com vários conjuntos de dados, faz sentido manter a região e os dados separados e juntá-los ao cliente. Muitos dos meus exemplos têm arquivos CSV (ou TSV) separados por esse motivo. Dessa forma, o TopoJSON para estados e condados dos EUA ou países do mesmo modo pode ser reutilizado, em vez de criar o TopoJSON separado para cada exemplo.
Por outro lado, se você usar essa geografia apenas uma vez , provavelmente deverá “inserir” os dados na geografia como propriedades, apenas para simplificar o código. Essa abordagem é mais simples porque você só precisa carregar um único arquivo (portanto, sem queue.js ) e, como os dados são armazenados como propriedades de cada recurso, não é necessário associá-los ao cliente (portanto, não d3. mapa ).
Nota lateral: TSV e CSV geralmente são muito mais eficientes no armazenamento de propriedades do que GeoJSON e TopoJSON, simplesmente porque o último deve repetir os nomes de propriedades em todos os objetos. O tamanho do arquivo pode ser outro motivo para armazenar seus dados em um arquivo separado e ingressá-lo no cliente.
Seus dados já estão vinculados à geografia (por exemplo, uma propriedade do seu shapefile)?
Supondo que você respondeu "não" à primeira pergunta e deseja incluir os dados na geografia (em vez de fazê-lo no cliente), como você faz isso depende do formato dos dados.
Se seus dados já são propriedade do seu shapefile, use
topojson -p
para controlar quais propriedades são salvas no arquivo TopoJSON gerado. Você também pode usar isso para renomear propriedades e coagi-las a números também. Veja Vamos fazer um mapa para exemplos.Se seus dados estiverem em um arquivo CSV ou TSV separado, use topojson -e (além de
-p
) para especificar um arquivo de propriedades externo que possa ser associado aos seus recursos geográficos. Fazendo o exemplo do wiki, se você tiver um arquivo TSV como este:Usando
-e
, você pode mapear isso para uma propriedade de saída numérica denominada “desemprego”:Um exemplo dessa abordagem é a população de Kentucky choropleth, bl.ocks.org/5144735 .
fonte
Boa pergunta. Um dos exemplos que você forneceu parece fazer o truque, embora seja difícil de seguir.
Você observará que o exemplo possui dois arquivos de dados externos, us.json e desemprego.tsv . Você pode pensar no desemprego.tsv como seu perigo.csv; us.json são os recursos geográficos aos quais você deseja associar parâmetros do danger.csv. Este último, unemployment.tsv, tem
id
erate
campos onde aid
é o mesmo que oid
de us.json.É no cliente com D3 que você deve mesclar seus dados e recursos , pelo menos neste exemplo. É no cliente que a taxa de desemprego, neste exemplo, é associada aos recursos do condado, usando a função d3.map () . É aqui que ele é inicializado:
E é aqui que
rate
é mapeado paraid
:Devo admitir que não sei para que
queue()
serve, mas não é importante para esta discussão. O que é importante observar é queooid
campo em cada característica do condado é substituído pelo desempregorate
.rate
é agora acessível pelo identificador partilhadaid
( EDIT: Como @ blord-Castillo pontos para fora, isto é, na verdade, a geração de uma nova matriz associativa, ou hash da chave, onde orate
é mapeado para oid
). É aqui querate
é chamado para fins de simbologia (aqui, classes CSS predefinidas estão disponíveis para cada quantil):Onde a
quantize()
função retorna o nome da classe CSS que deve ser usada para estilizar esse recurso (município) com base em sua taxa de desemprego, que agora é definida noid
campo do recurso .fonte
Primeiro, a primeira linha do seu csv deve ser uma lista separada por vírgula de nomes de colunas para usar esse método. Se isso não for possível, adicione um comentário sobre isso e verei se consigo descobrir como usar em
d3.csv.parseRows
vez ded3.csv.parse
.d3.csv.parse
é chamado pela função avaliador em.defer(function, url, assessor)
.Vou assumir que seu arquivo agora está assim:
Com isso, você pode criar um hash de pesquisa do ISO3 para o nível de perigo.
Passo a passo do código
Primeiro, você cria um objeto d3.map () que funcionará como seu hash da chave e o armazena na variável dangerByISO3.
Use fila para carregamento paralelo.
Carregue seu topojson como o primeiro argumento a ser passado para a função de espera (após erro). Observe o estilo aqui em que esta função está encadeada
queue()
, mas listada em uma linha separada (não há ponto e vírgula finalqueue()
).Duas coisas estão acontecendo aqui. Primeiro, você está carregando danger.csv como seu segundo argumento a ser passado para a função de espera. Como você verá abaixo, esse argumento não é realmente usado. Em vez disso, é fornecido um argumento de avaliador para a função de carregamento, d3.csv. Esse avaliador processará cada linha do csv. Nesse caso, chamamos a função set em dangerByISO3 para que, para cada combinação de uma
iso
chave, definamoslevel
como o valor correspondente a essa chave. A+d.level
notação usa unário+
para coagir o valor de d.level a um número.Depois que as duas fontes de dados são carregadas, elas são passadas como dois argumentos separados para a função
ready()
. O primeiro argumento para o retorno de chamada é sempre o primeiro erro que ocorreu. Se nenhum erro ocorreu, nulo será passado como o primeiro argumento. O segundo argumento é a primeira fonte de dados (resultado da primeira tarefa) e o terceiro argumento é a segunda fonte de dados (resultado da segunda tarefa).Esta é a função de retorno de chamada
ready()
. Primeiro, tomamos oerror
argumento que deve ser nulo se as duas tarefas de carregamento forem concluídas com êxito (você deve realmente adicionar linguagem para capturar e manipular erros). A seguir, tomamos os dados do topojson como objetocountries
. Esses dados devem ser processados no corpo da função com algo parecido.data(topojson.feature(world,world.objects.countries).features)
. Comoready()
não adota um terceiro argumento, o resultado da segunda tarefa, nosso csv, é simplesmente descartado. Nós o usamos apenas para criar o hash da chave e não precisamos dele depois disso.fonte