Me gustaría mapear un coroplés mundial para mostrar con D3, a la:
Tengo un conjunto de datos que me gustaría mostrar que está codificado para las teclas ISO-alpha-3. Entonces...
danger.csv
iso,level
AFG,100
ALB,0
DZA,12
etc.
Siguiendo las instrucciones sobre topojson, sé que puedo hacer ...
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 producir un mapa mundial json que está identificado por ISO3.
Mi pregunta es: ¿en qué punto del flujo de trabajo debo fusionar los datos de danger.csv en los datos geográficos? Anteriormente había trabajado con qGIS como GUI, pero ¿dónde / debería / ocurrir la fusión? En el .shp? ¿Después del ogr2ogr? ¿Dinámicamente en el navegador después del encogimiento topojson (como aquí http://bl.ocks.org/mbostock/4060606 http://bl.ocks.org/mbostock/3306362 )?
Soy bastante bueno con Python, pero bastante nuevo en JavaScript, y me encuentro copiando y pegando ejemplos de Bostock más que ser un codificador generativo allí.
(También tengo un seguimiento relacionado, pero más complicado, en Stackoverflow que tal vez debería migrar aquí: /programming/18604877/how-to-do-time-data-in-d3-maps )
Respuestas:
Hágase dos preguntas:
¿Vas a reutilizar la geografía en múltiples conjuntos de datos?
Si usará la misma geografía con múltiples conjuntos de datos, entonces tiene sentido mantener la geografía y los datos separados, y unirlos en el cliente. Muchos de mis ejemplos tienen archivos CSV (o TSV) separados por este motivo. De esta manera, el TopoJSON para los estados y condados de EE. UU. O los países del mundo también se pueden reutilizar, en lugar de crear TopoJSON por separado para cada ejemplo.
Por otro lado, si solo usará esta geografía una vez , entonces probablemente debería "hornear" los datos en la geografía como propiedades, aunque solo sea para simplificar el código. Este enfoque es más simple porque solo necesita cargar un solo archivo (por lo que no hay queue.js ), y dado que los datos se almacenan como propiedades de cada característica, no necesita unir los datos en el cliente (por lo tanto, no d3. mapa )
Nota al margen: TSV y CSV a menudo son mucho más eficientes para almacenar propiedades que GeoJSON y TopoJSON, simplemente porque este último debe repetir los nombres de propiedad en cada objeto. El tamaño del archivo puede ser otra razón para almacenar sus datos en un archivo separado y unirlos en el cliente.
¿Sus datos ya están vinculados a la geografía (por ejemplo, una propiedad de su shapefile)?
Suponiendo que respondió "no" a la primera pregunta y desea incorporar los datos a la geografía (en lugar de hacerlo en el cliente), la forma de hacerlo depende del formato de los datos.
Si sus datos ya son una propiedad de su shapefile, use
topojson -p
para controlar qué propiedades se guardan en el archivo TopoJSON generado. También puede usar esto para cambiar el nombre de las propiedades y obligarlas a números, también. Vea Hagamos un mapa para ver ejemplos.Si sus datos están en un archivo CSV o TSV separado, use topojson -e (además de
-p
) para especificar un archivo de propiedades externo que se pueda unir a sus características geográficas. Cribando el ejemplo de la wiki, si tuviera un archivo TSV como este:Utilizando
-e
, puede asignar estos a una propiedad de salida numérica llamada "desempleo":Un ejemplo de este enfoque es el choropleth de la población de Kentucky, bl.ocks.org/5144735 .
fuente
Buena pregunta. Uno de los ejemplos que proporcionó parece hacer el truco, aunque es difícil de seguir.
Notará que el ejemplo tiene dos archivos de datos externos, us.json y desempleo.tsv . Puedes pensar en paro.tsv como si fuera tu peligro.csv; us.json son las características geográficas con las que desea asociar parámetros de danger.csv. El último, paro.tsv, tiene
id
yrate
campos donde elid
es el mismo queid
en us.json.Es en el cliente con D3 que debe fusionar sus datos y características , al menos en este ejemplo. Es en el cliente que la tasa de desempleo, en este ejemplo, se une a las características del condado, utilizando la función d3.map () . Aquí es donde se inicializa:
Y aquí es donde
rate
se asigna aid
:Debo admitir que no sé para qué
queue()
sirve, pero no es importante para esta discusión. Es importante tener en cuenta queelelid
campo en cada característica del condado se reemplaza por el desempleorate
.rate
es ahora accesible por el identificador comúnid
( EDIT: Como @ blord-Castillo señala, esto es en realidad la generación de una nueva matriz asociativa, o hash de clave, donde elrate
se asigna alid
). Aquí es donderate
se llama a los fines de simbología (aquí, las clases CSS predefinidas están disponibles para cada cuantil):Donde la
quantize()
función devuelve el nombre de la clase CSS que debe usarse para diseñar esa característica (condado) en función de su tasa de desempleo, que ahora se define en elid
campo de la característica .fuente
En primer lugar, la primera fila de su csv debe ser una lista separada por comas de nombres de columna para usar este método. Si esto no es posible, agregue un comentario al respecto y veré si puedo averiguar cómo usarlo en
d3.csv.parseRows
lugar de hacerlod3.csv.parse
.d3.csv.parse
es llamado por la función de evaluador en.defer(function, url, assessor)
.Voy a asumir que su archivo ahora se ve así:
Con esto, puede crear un hash de búsqueda desde ISO3 hasta el nivel de peligro.
Tutorial de código
Primero crea un objeto d3.map () que funcionará como el hash de su clave y lo almacena en la variable dangerByISO3.
Utilice la cola para carga paralela.
Cargue su topojson como el primer argumento que se pasará a la función de espera (después del error). Tenga en cuenta el estilo aquí donde esta es una función encadenada
queue()
, pero aparece en una línea separada (no hay punto y coma finalizadoqueue()
).Dos cosas están sucediendo aquí. Primero, está cargando danger.csv como su segundo argumento para pasar a la función de espera. Como verá a continuación, este argumento no se usa realmente. En cambio, se proporciona un argumento evaluador para la función de carga, d3.csv. Este asesor procesará cada fila del csv. En este caso, llamamos a la función set en dangerByISO3 para que, para cada combinación de una
iso
tecla, establezcamoslevel
el valor como el que va con esa tecla. La+d.level
notación usa unario+
para coaccionar el valor de d.level a un número.Una vez que se cargan ambas fuentes de datos, se pasan como dos argumentos separados a la función
ready()
. El primer argumento para la devolución de llamada es siempre el primer error que ocurrió. Si no se produjo ningún error, se pasará nulo como primer argumento. El segundo argumento es la primera fuente de datos (resultado de la primera tarea), y el tercer argumento es la segunda fuente de datos (resultado de la segunda tarea).Esta es la función de devolución de llamada
ready()
. Primero tomamos elerror
argumento que debería ser nulo si las dos tareas de carga se completan con éxito (en realidad, debe agregar un idioma para detectar y manejar los errores). A continuación tomamos los datos de topojson como el objetocountries
. Estos datos deben procesarse en el cuerpo de la función con algo como.data(topojson.feature(world,world.objects.countries).features)
. Comoready()
no toma un tercer argumento, el resultado de la segunda tarea, nuestro csv, simplemente se descarta. Solo lo usamos para construir el hash clave y no lo necesitamos después de eso.fuente