SAS: Mapa de distritos de Barcelona

La semana pasada publiqué el mapa de distritos de Madrid, así qie creo que es justo también publicar el mapa de distritos de Barcelona. En este caso los datos los he encontrado en la sección de periodismo de datos de la Vanguardia.

Distritos_Barcelons

filename file "&ruta/shapefiles_barcelona_distrito.shp" encoding="UTF-8";
proc mapimport datafile=file
out = BARCELONA;
run;

proc sort data=BARCELONA out=DISTRITO nodupkey;
by c_distri;
run;

proc gmap data=DISTRITO map=BARCELONA;
id c_distri;
title "Distritos del municipio de Barcelona";
choro n_distri/discrete;
run;

He encontrado también el mapa de secciones censales de Barcelona.

DCensal_Barcelona

filename file "&ruta/elecciones_congreso_distrito_censal_bcn.shp" encoding="UTF-8";
proc mapimport datafile=file
out = CEN_BARCELONA;
run;

proc sort data=CEN_BARCELONA out=DISTRITO nodupkey;
by cartodb_id;
run;

proc gmap data=DISTRITO map=BARCELONA;
id cartodb_id;
title "Distritos y secciones censales del municipio de Barcelona";
choro distrito/discrete;
run;

SAS: Mapa de departamentos del Perú

Como sabéis los que me conocéis bien, soy un enamorado del Perú, así que voy a hacer un pequeño homenaje a Perú con esta entrada en la que quiero profundizar en cómo trabajar con gráficos de mapas. En esta ocasión he obtenido los shapefiles de la web de geogpsperu, y los datos sobre turismo que estoy representando del Observatorio Turístico del Perú.

Este es un mapa con más detalles que el anterior que he publicado Mapa de distritos de Madrid. Aquí, además de representar la distribución de una variable continua en un mapa, voy a introducir las etiquetas, en este caso de los departamentos del país.

MApa_turistas_Peru

Y el código con el que lo he generado es el siguiente, que paso a explicar:

filename file "&ruta/DEPARTAMENTOS.shp" encoding="UTF-8";
proc mapimport datafile=file out = PERU;
run;

proc sql;
     create table DEPARTAMENTOS as
     select iddpto,
            departamen,
            avg(x) as x,
            avg(y) as y
     from PERU
     group by 1,2;
quit;

proc sql;
    create table DEPARTAMENTOS2 as
    select a.*,
           b.turistas
    from DEPARTAMENTOS a
    left join TURISTAS b
    on translate(lowcase(a.departamen),'aeiou','áéíóú') = 
            translate(lowcase(b.departamento),'aeiou','áéíóú');
quit;

data LABELS;
    length color $8 text $55;
    set DEPARTAMENTOS2;
    style='Thorndale AMT';
    function='label';
    xsys='2';
    ysys='2';
    hsys='3';
    when='a';
    text=departamen;
    color='FFFFFFFF'; 
    size=2; 
    if departamen in ('LIMA','AYACUCHO','CAJAMARCA') then y=y-0.5;
run;

legend1 label=("Turistas extranjeros:");
proc gmap data=DEPARTAMENTOS2 map=PERU; 
    id iddpto;
    title "Turistas extranjeros en Perú (2015)"; 
    choro turistas / annotate=LABELS 
                     midpoints=5000 10000 50000 100000 500000
                     legend=legend1;
run;

Además dispongo de unos datos sobre el volumen de turistas que visitaron Perú que introduzco en una tabla llamada TURISTAS:

data TURISTAS;
    infile datalines dsd missover;
    format Departamento $20.;
    input Departamento $ Turistas;
cards;
Amazonas,	4157
Ancash,	61384
Apurimac,	5326
Arequipa,	175271
Ayacucho,	12956
Cajamarca,	1270
Callao,	
Cusco,	967266
Huancavelica,	2530
Huánuco,	1735
Ica,	167266
Junín,	8402
La Libertad,	55536
Lambayeque,	75943
Lima,	2112090
Loreto,	67371
Madre de Dios,	74738
Moquegua,	10655
Pasco,	1074
Piura,	25024
Puno,	198817
San Martín,	9833
Tacna,	885744
Tumbes,	152459
Ucayali,	5929
;
run;

Lo primero por lo que empiezo es con la importación del shapefile en SAS con el proc mapimport que guardo en la tabla PERU. Esta será la tabla que contenga la representación del mapa para el gráfico.

Luego necesito crear una tabla que contenga los datos a representar (dentro del mapa) para cada departamento. Para ello tomo los identificadores de los departamentos (campo ID para el proc gmap) y el nombre del departamento y calculo los puntos medios con objeto de situar allí las etiquetas con el nombre de esos mismos departamentos. Posteriormente, solo queda cruzar la tabla anterior con la de TURISTAS. Como ambas fuentes de datos no tienen el mismo origen, y una tiene tildes en los nombres y otra no en e campo de cruce, utilizo la función translate.

El siguiente paso es crear la tabla LABELS que contiene la información necesaria para la representación de las etiquetas en el gráfico. Esta técnica se puede utilizar tanto para representar etiquetas en un mapa, como en cualquier otro tipo de gráfico de líneas, de barras, etc.

La tabla LABELS debe incorporar cierto tipo de campos con un nombre y significado específico y que luego será interpretados por el parámetro ANNOTATE que, entre otros son los siguientes:

  • X e Y: Son las coordenadas con las que se representa el mapa. Debe estar en el mismo sistema de representación: grados, radianes, etc.
  • XSYS, YSYS y HSYS: Representan el tipo de coordenadas que se están incluyendo en X e Y. Como nuestras variables X y Y son latitud y longitud en grados utilizaremos la combinación de valores 2, 2, 3 para estas variables.
  • function: Indica el tipo de representación que se va a hacer en el gráfico. En nuestro caso dibujaremos una etiqueta por lo que su valor deberá ser «label», pero podríamos representar puntos («point»), líneas («line»), flechas («arrow»), etc.
  • style: Es el estilo, fuente o patrón que se va a utilizar. Depende de function.
  • when: Indica el momento en que se va a dibujar el contenido descrito (la etiqueta en nuestro caso). Nosotros queremos dibujar las etiquetas después del gráfico para que se representen encima y se vean, por lo que le damos valor «a» de after.
  • text: Indica el valor de la etiqueta que se va a representar.
  • color: El color del texto.
  • size: El tamaño del texto.

Al final hago una pequeña corrección de las etiquetas para algunos departamentos para que la representación del gráfico sea satisfactoria.

Finalmente, el ultimo paso es el proc gmap, donde utilizo los tres conjuntos de datos anteriores PERU (contiene los datos del mapa), DEPARTAMENTOS2 (contiene los datos a representar en el mapa sobre cuántos turistas hay por departamento) y LABELS (que contiene los datos para situar y representar las etiquetas con los nombres).

El parámetro id representa la variable que identifica cada zona distinta del mapa. choro es una de las opciones de representación de gráficos que indica que la variable a representar («turistas») se representará con una escala de colores en la superficie del gráfico en función de su valor.

choro> tiene varios parámetros a su vez: annotate que identifica la tabla con los datos de etiquetas («LABELS»). midpoints que permite personalizar los puntos de corte de una variable continua como la nuestra, de forma que cada punto de corte indicará que se representará con un tono de color distinto. legend identifica el título que se le va a dar a la leyenda del gráfico.

SAS: Mapa de distritos de Madrid

Pues eso, para aquellos a los que os guste dibujar mapas y gráficos chulos y no os importe currároslo un poco aquí tenéis un pequeño código para dibujar los distritos del municipio de Madrid.

Distritos de Madrid

La fuente de datos es el Instituto de Estadística de la Comunidad de Madrid que publica shapes en este link. Este ficheros contiene todos los distritos de la Comunidad.

filename file "&ruta/200001693.shp" encoding="UTF-8";
proc mapimport datafile=file
out = MADRID;
run;

proc sort data=MADRID out=DISTRITO nodupkey;
by geocodigo;
run;

data DISTRITO;
set DISTRITO;
if substr(geocodigo,1,3)='079';
distrito = substr(desbdt,8);
run;

proc gmap data=DISTRITO map=MADRID;
id geocodigo;
choro distrito/discrete;
run;

Gráficos de mapa con shapefiles: coronavirus

Vamos a tratar como usar shapefiles para dibujar mapas con SAS. Utilizaré para los ejemplos datos de la trágica lacra que nos asola estos días, la enfermedad del coronavirus.

Un shapefile es un formato vectorial de almacenamiento de información geográfica, es además un fichero multiarchivo porque requiere de varios ficheros para poder ser interpretado. Son varios los ficheros que pueden estar incluidos, pero al menos deben existir estos tres: .shp, .shx y .dbf.

SAS puede utilizar proc mapimport para importar el shapefile y convertirlo en tablas SAS que podremos tratar para construir gráficos. Además, en este caso, le vamos a asociar datos sobre el coronavirus consultados a fecha 4 de abril en la siguiente página de Sanidad.

proc gmap se encarga de dibujar el mapa que está definido en el parámetro map= y los datos para los gráficos o los colores de representación se encuentran informados por el contenido del parámetro data=. El statement choro (jocoso nombre para los peruanos) indica la variable que se utilizará para representar las distintas zonas del mapa con un color más o menos intenso según su valor relativo. La opción choro variable/discrete indica una variable no continua, por lo que los colores representados con colores distintos.

coronavirus1

filename file "&ruta/gadm36_ESP_1.shp" encoding="UTF-8";
proc mapimport datafile=file out = GDIS;
run;

proc sort data=GDIS out=COMUNIDAD (rename=(name_1 = comunidad)) nodupkey;
    by gid_1;
run;

/* Adecuamos la posición de las Islas Canarias para tener un mapa más grande */;
data GDIS;
    set GDIS;
    if name_1='Islas Canarias' then do;
        x = x + 20;
        y = y + 7;
    end;
run;

/* Añadimos la información del coronavirus */
data CORONAVIRUS;
    infile datalines dsd missover;
    format contagiados 8. comunidad $50. fallecidos 8.;
    input contagiados comunidad $ fallecidos;
    cards;
    36249, 'Comunidad de Madrid', 4723
    24734, 'Cataluña', 2508
    7875, 'Castilla y León', 723
    9324, 'Castilla-La Mancha', 989
    8187, 'País Vasco', 477
    7869, 'Andalucía', 426
    6901, 'Comunidad Valenciana', 571
    5625, 'Galicia', 159
    2972, 'Comunidad Foral de Navarra', 171
    3078, 'Aragón', 251
    2405, 'La Rioja', 128
    1979, 'Extremadura', 208
    1522, 'Principado de Asturias', 76
    1564, 'Islas Canarias', 78
    1384, 'Cantabria', 68
    1271, 'Islas Baleares', 71
    1188, 'Región de Murcia', 51
    152, 'Ceuta y Melilla', 3
    ;
run;

proc sql;
    create table COMUNIDAD2 as
    select a.*,
           b.contagiados,
           b.fallecidos
    from COMUNIDAD a
    left join CORONAVIRUS b
    on a.comunidad = b.comunidad;
quit;

proc gmap data=COMUNIDAD2 map=GDIS;
    title 'Contagiados por coronavirus en España';
    id gid_1;
    choro contagiados;
run;

Utilizar block en vez de choro representará los datos como columnas verticales dentro de cada zona. La opción legend=legend se utiliza para indicar que el color de las columnas y de la leyenda serán iguales.

coronavirus2

proc gmap data=COMUNIDAD2 map=GDIS;
    title 'Contagiados por coronavirus en España';
    id gid_1;
    block contagiados / legend=legend;
run;