#Taller CartoDB GDF
About Santiago:
Civic Technologist @CartoDB
@namessanti
El Dasboard es el centro de control para tu data, tus mapas, y tu cuenta. Es muy importante saber la diferencia entre mapas y datasets en CartoDB.
- Puedes tener varios mapas con la misma data.
- Crear un diseño para la data, no es lo mismo que crear un mapa.
La barra azul en la parte de arriba te deja:
- Puedes navegar entre data y mapas
- piensa sobre tus datasets como la espina de tus mapas. Trabajar en el Dataset View deja que manipules y diseñes los datos directamente.
- Visitar el CartoDB gallery
- apprender nuevas tecnicas en la pagina de documentacion.
El icono a la mano derecha te deja:
- Ver y organizar tus account settings
- Visitar to pagina publica
- Esta pagina es importante porque es el lugar principal para compartir y publicar tus mapas/
- Ver tu API key
- Que va a ser muy importante para usar CartoDB.js y algunos de los elementos de los APIs y OGR.
Haz click en el boton verde New Map.
De aqui hay varias formas de importar datos.
Puedes:
- Crear un mapa sin data
- Mirar data en el data library
- Usar data que ya existe en tu cuenta CartoDB, usar data que ha sido compartido contigo, o precionar
- Connect a new dataset.
- Aqui puedes meter data de tu computadora, un URL, o los varios conectores para data y mapas en vivo (Google, Twitter, URL).
##CartoCSS - El lenguage de diseño para mapas
CartoCSS es uno de los leguajes mas importantes para diseñar mapas en CartoDB, y para diseñar interacion usando CartoDB.js
Cascading Style Sheets Para Mapas
CartoCSS es muy similar en estructura a Cascading Style Sheet codigo para diseño en la web, o CSS. El codigo contiene un selector que llama a el elemento HTML que estas estilando, y propiedades con valores que definen el diseño de los elementos.
selector {
property: value;
}
CartoCSS tiene muchas opciones para diseñar que no existen en el Wizard normal. Los selectadores son tipicamente el nombre de el dataset en tu cuenta de CartoDB. Pero tambien pueden ser otros elementos:
Map {
marker-fill: #ffcc00;
}
Importemos datos a CartoDB usando este link para las colonias de la Ciudad de Mexico
En la vista de mapa, haz click en el panel de CSS en el menu a la derecha. Aqui puedes escribir codigo directamente a tu mapa, Y este mismo codigo se puede usar en HTML y CartoDB.js.
El CartoCSS defecto.
Cuando importas data a CartoDB, El codigo de defecto se ve como algo asi:
#limites_colonias{
polygon-fill: #FF6600;
polygon-opacity: 0.7;
line-color: #FFF;
line-width: 0.5;
line-opacity: 1;
}
Tambien, cuando haces cambios en el editor, los cambios se representan en vivo el el panel de CSS.
Probemos unos parametros que no se encuentran en el Wizard.
####diseño condicional
Con CartoCSS, no solo es posible definir los estilos de la tabla, pero tambien es posible diseñar los datos precisos llamando directamente a la tabla usando []
despues de el nombre de tabla en cualquier punto de el codigo con algo que define lo que buscas <
, >
, =
, o !=
para desigualdad.
#limites_colonias{
polygon-fill: #FF6600;
polygon-opacity: 0.7;
line-color: #FFF;
line-width: 0.5;
line-opacity: 1;
[nombre='ZONA RUSTICA'] {
polygon-fill: blue;
}
}
El CartoCSS se lee de arriba a abajo. Si cambias el estilo en el codigo despues de definir un estilo inicial, el estilo cambiara. Aqui vamos entroducir una nueva propiedad que no se encuentra en el Wizard, line-dasharray
. Aplica este codigo abajo de tu estilo defecto, Y mira como cambia el mapa:
#limites_colonias [nombre='ZONA RUSTICA'] {
polygon-fill: blue;
line-width: 3;
line-color: yellow;
line-dasharray: 5, 5;
}
Llamar a tu data tambien se puede usar como un valor. copiando este codigo, vamos a crear nombres visibles usando ::labels
despues de el nombre de la tabla, y [nombre]
como el valor.
#limites_colonias::labels {
text-name: [nombre];
text-face-name:'Open Sans Semibold';
text-size: 7;
text-label-position-tolerance: 5;
text-fill: #a43b08;
text-dy: 0;
text-allow-overlap: false;
text-placement: point;
text-placement-type: simple;
text-character-spacing: 2;
text-halo-radius: 3;
}
Vas a notar que no todoas las colonias tienen labels. Esto es por el text-allow-overlap:false
, que solo deja labels aparecer cuando no interfieren con otros labels. Si te acercas a partes de el mapa, los labels apareceran dinamicamente.
Imagenes con CartoCSS
otra propiedad de CartoCSS es polygon-pattern-file
. esta propiedad toma un URL de una imagen como el valor para llenar polygons. Puedes modificar la opacidad usando polygon-pattern-opacity
y tambien polygon-fill-color
.
Hay que usar una variedad de todos los parametros para ver como funcionan juntos:
#limites_colonias{
polygon-fill: #FF6600;
polygon-opacity: 0.7;
line-color: #FFF;
line-width: 0.5;
line-opacity: 1;
[nombre!='ZONA RUSTICA'] {
polygon-fill: transparent;
}
[nombre='ZONA RUSTICA'] {
polygon-fill: blue;
line-width: 3;
line-color: yellow;
line-dasharray: 5, 5;
polygon-pattern-file: url(https://s3.amazonaws.com/com.cartodb.users-assets.production/production/stephaniemongon/assets/20150607041630diag-w.png);
polygon-pattern-opacity: 0.3;
}
}
#Torque
Comenzemos regresando a el dashboard y hay que crear un nuevo mapa, metiendo datos de accidentes para Denver, CO usando este link: Accidentes de Tráfico para Denver, CO
Encuentra tu taba traffic_accidents
y comenzemos haciendo una nueva visualización
Introduccion: duration
, steps
, trails
, resolution
#traffic_accidents[frame-offset=2] {
marker-width:10;
marker-fill-opacity:0.225;
}
El offset esta directamente conectado a -torque-frame-count:512;
Map {
-torque-frame-count:512;
-torque-animation-duration:30;
-torque-time-attribute:"cartodb_id";
-torque-aggregation-function:"CDB_Math_Mode(torque_category)";
-torque-resolution:2;
-torque-data-aggregation:linear;
}
Es SQL incrustado en CartoCSS!
CDB_Math_Mode(district_i)
count(*)
sum(income)
#traffic_accidents[value=1] {
marker-fill: #A6CEE3;
}
Mapas de categoria animados usan el aggregate function y CDB_Math_Mode
para crear valores ( values
) previsibles para el diseño. Veamos como funciona:
Map {
-torque-frame-count:512;
-torque-animation-duration:30;
-torque-time-attribute:"cartodb_id";
-torque-aggregation-function:"CDB_Math_Mode(district_i)";
-torque-resolution:2;
-torque-data-aggregation:linear;
}
#traffic_accidents{
comp-op: source-over;
marker-fill-opacity: 0.9;
marker-line-color: #FFF;
marker-line-width: 1.5;
marker-line-opacity: 1;
marker-type: ellipse;
marker-width: 6;
marker-fill: #FF9900;
}
#traffic_accidents[frame-offset=1] {
marker-width:8;
marker-fill-opacity:0.45;
}
#traffic_accidents[frame-offset=2] {
marker-width:10;
marker-fill-opacity:0.225;
}
#traffic_accidents[value=1] {
marker-fill: #A6CEE3;
}
#traffic_accidents[value=2] {
marker-fill: #1F78B4;
}
#traffic_accidents[value=3] {
marker-fill: #B2DF8A;
}
#traffic_accidents[value=4] {
marker-fill: #33A02C;
}
#traffic_accidents[value=5] {
marker-fill: #FB9A99;
}
#traffic_accidents[value=6] {
marker-fill: #E31A1C;
}
#traffic_accidents[value=7] {
marker-fill: #FDBF6F;
}
Valores estan calculados dentro de cada bin geotemporal. Es una combinacion de -torque-frame-count
y -torque-resolution
Veamos este codigo para comenzar:
Map {
-torque-frame-count:256;
-torque-animation-duration:30;
-torque-time-attribute:"first_occu";
-torque-aggregation-function:"count(cartodb_id)";
-torque-resolution:2;
-torque-data-aggregation:linear;
}
#traffic_accidents{
comp-op: lighter;
marker-fill-opacity: 0.9;
marker-line-color: #FFF;
marker-line-width: 0;
marker-line-opacity: 1;
marker-type: ellipse;
marker-width: 1;
marker-fill: #F84F40;
}
#traffic_accidents[value>2] {
marker-width:2;
}
#traffic_accidents[value>3] {
marker-width:4;
}
#traffic_accidents[value>4] {
marker-width:8;
}
#traffic_accidents[frame-offset=1] {
marker-width:2.5;
marker-fill-opacity:0.2;
}
#traffic_accidents[frame-offset=2] {
marker-width:4.5;
marker-fill-opacity:0.1;
}
Miremos el elemento Map
.
Map {
-torque-frame-count:24;
-torque-animation-duration:30;
-torque-time-attribute:"first_occu";
-torque-aggregation-function:"count(cartodb_id)";
-torque-resolution:16;
-torque-data-aggregation:linear;
}
y el diseño:
#traffic_accidents{
comp-op: lighter;
marker-fill-opacity: 0.9;
marker-line-color: #FFF;
marker-line-width: 0;
marker-line-opacity: 1;
marker-type: ellipse;
marker-width: 1;
marker-fill: #F84F40;
}
#traffic_accidents[value>3] {
marker-width:2;
}
#traffic_accidents[value>5] {
marker-width:3;
}
#traffic_accidents[value>7] {
marker-width:6;
}
#traffic_accidents[value>10] {
marker-width:8;
}
Regresando a el mapa de categoria, miremos que pasa cuando usamos Torque sin animacion:
Map {
-torque-frame-count:1;
-torque-animation-duration:0;
-torque-time-attribute:"cartodb_id";
-torque-aggregation-function:"CDB_Math_Mode(district_i)";
-torque-resolution:1;
-torque-data-aggregation:linear;
}
#traffic_accidents{
comp-op: source-over;
marker-fill-opacity: 0.9;
marker-line-color: #FFF;
marker-line-width: 1.5;
marker-line-opacity: 1;
marker-type: ellipse;
marker-width: 6;
marker-fill: #FF9900;
}
#traffic_accidents[value=1] {
marker-fill: #A6CEE3;
}
#traffic_accidents[value=2] {
marker-fill: #1F78B4;
}
#traffic_accidents[value=3] {
marker-fill: #B2DF8A;
}
#traffic_accidents[value=4] {
marker-fill: #33A02C;
}
#traffic_accidents[value=5] {
marker-fill: #FB9A99;
}
#traffic_accidents[value=6] {
marker-fill: #E31A1C;
}
#traffic_accidents[value=7] {
marker-fill: #FDBF6F;
}
Para que sirve? - Mejor control sobre el diseño de intensidad.
Map {
-torque-frame-count:1;
-torque-animation-duration:0;
-torque-time-attribute:"cartodb_id";
-torque-aggregation-function:"count(district_i)";
-torque-resolution:1;
-torque-data-aggregation:linear;
}
#traffic_accidents{
comp-op: source-over;
marker-fill-opacity: 0.9;
marker-line-color: #FFF;
marker-line-width: 0;
marker-line-opacity: 1;
marker-type: ellipse;
marker-width: 2;
marker-fill: #FFCC00;
}
#traffic_accidents[value>1] {
marker-fill: #FFA300;
}
#traffic_accidents[value>2] {
marker-fill: #FF9900;
}
#traffic_accidents[value>3] {
marker-fill: #FF5C00;
}
#traffic_accidents[value>4] {
marker-fill: #FF6600;
}
#traffic_accidents[value>5] {
marker-fill: #FF2900;
}
Tomen nota que aqui estamos usando CartoCSS condicional otra vez, en otra capacidad, haciendo calculaciones basicas con >
, <
, o =
.
Hay que crear un nuevo columno titulado offense_n
, de tipo number
En el panel de SQL corramos la siguiente consulta para popular esta columna:
UPDATE traffic_accidents SET offense_n = 1 WHERE offense_ty = 'traf-vehicular-homicide';
UPDATE traffic_accidents SET offense_n = 2 WHERE offense_ty = 'traffic-accident-dui-duid';
UPDATE traffic_accidents SET offense_n = 3 WHERE offense_ty = 'traf-vehicular-assault';
UPDATE traffic_accidents SET offense_n = 4 WHERE offense_ty = 'traffic-accident';
UPDATE traffic_accidents SET offense_n = 5 WHERE offense_ty = 'traffic-accident-hit-and-run';
Cambiemos la cabeza:
Map {
-torque-frame-count:64;
-torque-animation-duration:30;
-torque-time-attribute:"first_occu";
-torque-aggregation-function:"CDB_Math_Mode(offense_n)";
-torque-resolution:16;
-torque-data-aggregation:linear;
}
#traffic_accidents{
comp-op: source-over;
marker-fill-opacity: 0.6;
marker-line-color: #FFF;
marker-type: rectangle;
marker-width: 8;
marker-fill: #FF9900;
}
#SQL – Structured Query Language
CartoDB es una herramienta para manipulacion y visualización de data geo-espacial
SQL is es el lenguaje para manipular data, y tambien data en espacio.
SQL es facil de aprender y muy poderoso. Al comienzo es un poco raro, pero con un poco de entedimiento basico, puedes hacer análisis de datos increibles. Si, SQL es el lenguaje de mapas!
###Sintaxis Basico
La declaración mas basica es:
SELECT * FROM table_name
La * significa 'todo el la taba'. Esto significa que todas las filas y columnas de la tabla estan recibidas una vez cuando la consulta corre.
Algo mas complicado podria ser (solo un ejemplo):
SELECT
nombre,
altura,
edad
FROM
datos_de_organizacion
WHERE
nombre = 'Santiago'
AND (
altura > 1.8
OR
altura < 1.6
)
SELECT
es lo que pides (necesario)FROM
es de donde se encuentra la data (necesario)WHERE
es el filtro que estas pidiendo de la tabla (opcional)
La oración se lee: Seleciona (SELECT) el nombre, altura, y edad de (FROM) la tabla, donde (WHERE) el nombre es Santiago y la altura es mas que 1.8 metros, o menos que 1.6 metros.
Es importante recordar que cunado llamas a datos que son formato 'string' o palabras, se necita usar quotes en este formato: 'santiago'
. Para numeros esto ne es necesario
Tambien puedes agregar limites usando LIMIT n
(donde n es un numero >= 0). Esto regresa solo n entradas. además puedes usar ORDER BY column_name ASC
, que ordena la data ascendente (DESC es otra opcion). You can combine them to give you the top 20 largest districts by number of schools.
Probemos diferentes cosultas con nuestros propios datos.
Igual que antes, copien este URL para puntos de negocios industriales en la Ciudad De Mexico, y importenlo a CartoDB.
Que si queremos saber algo sobre solo algunos datos, o información sobre algo especifico en la tabla? Con SQL en CartoDB esto es super facil!
Hay que buscar las industrias solo en la localidad de Xochimilco con la fecha alta de Julio 2010:
SELECT * FROM industria
WHERE
localidad = 'XOCHIMILCO'
AND
fecha_alta = 'JULIO 2010'
Porque estamos trabajando con datos espaciales, estos cambios se pueden ver inmediatamente en el mapa. Estas consultas usando SQL son una de las bases para crear tableros dinamicos y interactivos usando CartoDB.js (Lo cubriremos en sesiones en el futuro)
- Hay miles de formas para manipular data usando SQL en CartoDB.
Probemos un par mas, y sin miedo experimenten con otras posiblidades:
Usa "Clear View" en el panel de SQL, y ahora Hay que unir dos columnas para poder rapidamente crear infowindows con mas contenido:
SELECT *, entidad||' con localidad: '||localidad AS entidad_localidad
FROM industria
Aqui selecionamos todo (*) y tambien creamos una nueva columna que usa ||
para unir la columna entidad, con las palabras ' con localidad ' y con la columna localidad. Si miras en tu tabla veras la columna entidad_localidad, y ahora puedes crear infowindows con esa columna.
- Es importante notar que
AS
se usa para crear nuevas columnas rapidamente usando SQL
Hay que probabr usando el ORDER BY
y LIMIT
.
En el panel de SQL en el mapa, agriegen esta consulta:
SELECT
the_geom,
the_geom_webmercator,
cartodb_id,
conse,
fecha_alta,
localidad,
FROM
industria
ORDER BY
conse
LIMIT
20
Aqui estamos selecionando solo las primeras 20 filas definido por conse
ascendente, y con solo las columnas conse
, the_geom
, cartodb_id
, fecha_alta
, y localidad
. Igual que antes, se puede ver los cambios en la tabla y el mapa.
###the_geom, the_geom_webmercator, y cartodb_id te habras dado cuenta que en trabajando con estos datos, hemos usado tres columnas que no existen en la tabla original. Hay tres columnas especiales en CartoDB:
-
the_geom: el Long/Lat en forma normalizada (SRID 4226)
-
the_geom_webmercator: Es una proyección basada en Mercator, pero optimizada para la web. Esta columna es necesaria para ver los datos el el mapa con cambios en vivo. Siempre asegurate que seleciones (
SELECT
) the_geom_webmercator para ver cambios rapidos! (SRID: 3857) -
cartodb_id: Es una columna que facilita la interacción en tus mapas. Sin esta columna, no es posible tener eventos de click o 'hover'
Por ejemplo, la consulta siguiente produce un mapa interactivo:
SELECT
the_geom_webmercator,
the_geom,
localidad,
cartodb_id
FROM
industria
Tambien puedes inspectar la columna invisible (the_geom_webmecator) usando la funcion de PostGIS ST_AsText
:
SELECT cartodb_id, ST_AsText(the_geom_webmercator) AS the_geom_webmercator
FROM industria
####Recursos iniciales
Despues de pasar un tiempo aprediendo el sintaxis basico, el mundo de data y analysis se abre casi sin limites.
- Puedes aprender mas SQL en la Academia de CartoDB
- SQL tiene capacidad para calcular varias funciones de matemáticas.
- Aqui hay talleres para aprender como usarlas rapidamente
Bastantes son funciones agregas, Que significa la necesidad de demonstrarlo en sus propias columnas.
#Mas SQL y análisis espacial con PostGIS
Hay que abrir nuestro mapa de colonias en la Ciudad de Mexico.
Piensa sobe estas como filtros temporales. El resultado aparece en el mapa, pero no cambia la tabla.
Hay que hacer unas consultas a nuestra data espacial.
Solo colonias al este de el centro de la Ciudad de Mexico
SELECT * FROM limites_colonias
WHERE
ST_XMin(the_geom) > -99.1333
Aqui estamos usando ST_XMin
para decir que la longitudad minima para visualizar necesita ser -99.1333.
Solo colonias a 5 Kilometros de el centro de la ciudad
SELECT * FROM limites_colonias
WHERE
ST_DWithin(the_geom, CDB_LatLng(19.4333, -99.1333), 5000, true)
Aqui estamos usando una funcion dentro de la otra. ST_DWithin
es una funcion para buscar datos dentro de una area especifica. CDB_LatLng
es una funcion especifica de CartoDB, ques pide un Lat/Long y distancia en metros para definir la area.
Puedes crear nuevas columnas y datos temporales para visualizar usando PostGIS.
SELECT *,
ST_Distance(the_geom, CDB_LatLng(19.4333, -99.1333)) d
FROM limites_colonias
Aqui creamos una nueva columna temporal 'd' midiendo distancia de cada dato de el centro de la ciudad.
Ahora podemos crear un mapa sin agregar la columna a los datos fijos.
En nuestro mapa de colonias, hay que agregar un layer usando este link para estaciones de bomberos
Ahora, hay que medir la distancia de cada colonia a las estaciones de bomberos mas cercanas.
Date cuenta, que de nuevo estamos creando una columna de distancias sando PostGIS, y tambien, estamos creando un alias para nuestra tabla limites_colonias
para hacer nuesrtas consultas mas rapidas y faciles.
SELECT *,
(SELECT ST_Distance(the_geom, c.the_geom) FROM estaciones_de_bomberos
ORDER BY the_geom <-> c.the_geom
LIMIT 1) d
FROM
limites_colonias c
En esta instacia, podemos determinar cuales son las colonias mas vulnerables en caso de emergencia de fuego.
####Contando puntos en polygon
Agriega de nuevo a nuestro mapa los puntos de industria
Y hagamos nuestras estaciones de momberos transparente.
Queremos contar las instancias de industrias en cada colonia para crear un mapa que nos dice donde hay mas industria que otros.
Crea una nueva columna en nustra tabla de colonias, y llamalo 'p_count'.
copis esta declaracion a tu panel de SQL:
UPDATE limites_colonias SET p_count = (SELECT count(*)
FROM estaciones_bomberos
WHERE ST_Intersects(estaciones_bomberos.the_geom, limites_colonias.the_geom))
Going back to our Wizard, we can now make a Choropleth map of fire instances in the various zones.
Es importante notar que estos datos no estan normalizados. Es mejor normalizar la data por area:
SELECT the_geom, the_geom_webmercator, cartodb_id, p_count, nombre,
(p_count / (ST_Area(the_geom::geography)/1000000))
as n_count
FROM limites_colonias
Modificando data se hace igual que en cualquier sistema de datos, pero usado consultas espaciales. Se Puede usar UPDATE
, INSERT
, o DELETE
.
ESTOS CAMBIOS CAMBIAN A TU TABA PERMANENTEMENTE! NO HAY BOTON PARA REGRESAR!
Si quieres, corre esta consulta para ver los resultados, pero recuerda que tus datos cambian las dos tablas permanentemente, y necesitaras importarlos de nuevo para obtener los datos completos.
Elimina todos los records a 0.03 grados de La Ciudad de Mexico
DELETE FROM limites_colonias
WHERE NOT ST_DWithin(the_geom, CDB_LatLng(19.4333, -99.1333), 0.20); DELETE FROM estaciones_de_bomberos
WHERE NOT ST_DWithin(the_geom, CDB_LatLng(19.4333, -99.1333), 0.20)
Tambien podemos agregar datos permanentemente a una tabla, en una nueva columna usando UPDATE
. hay que crear una nueva columna llamada 'distancia_de_bomberos' en nuestra taba de limites_colonias
, y despues correr esta consulta:
UPDATE
limites_colonias
SET
distancia_de_bomberos =
ST_Distance(the_geom,
(SELECT
the_geom
FROM estaciones_de_bomberos
ORDER BY the_geom <-> limites_colonias.the_geom
LIMIT 1)
)
Todos los datos que han usado en este taller hasta ahora has sido posibles por el SQL API
El SQL API te da accesso completo a toda las funciones que encuentras en el editor. Tipicamente, se usa para leer tablas de datos publicos, o sacar datos especificos usando solo un URL endpoint.
Tambien puedes:
SELECT
data privada para uso oficial usando tu autorizacion y API key- autorizado
INSERT
- autorizado
DELETE
- autorizado
UPDATE
Un ejemplo de SELECT anonimo:
http://andrew.cartodb.com/api/v2/sql?q=SELECT%20*%20FROM%20firestations_pt_mema%20LIMIT%2010
O saco solo las 10 estaciones mas cercanas a mi posicion usando:
SELECT * FROM firestations_pt_mema ORDER BY the_geom <-> my_location LIMIT 10
Pero en forma URL
SELECT * FROM firestations_pt_mema ORDER BY the_geom <-> CDB_LatLng(42.358, -71.064) LIMIT 10
Manana cubriremos como usar toda esta informacion para crear interaciones dinamicas usando cartoDB.js!
###Gracias!