Title Text

#LasCallesDeZaragoza

Jessica Sena

@jsenag
github.com/jessisena

Ingeniera informática Posgraduada UX

Visibilizar la escasa representación de mujeres en espacios públicos y digitales

Para conseguirlo:

Acción 1:

Crear un mapa mundial.


Representar las calles con nombres de mujer y de hombre. 

Acción 2:

Enlazar cada calle de mujer con su artículo en Wikipedia 


Identificar quiénes no tienen entrada 

Proceso técnico

2. Tratamiento de datos
https://blog.mapbox.com/mapping-female-versus-male-street-names-b4654c1e00d5
3. Generar el visor
1. Extracción de datos

1. Extracción de datos

OBJETIVO:
Obtener fichero con SÓLO las CALLES de una ciudad

Herramientas:
Tile Calculator - ​OSM QA Tiles - TileReduce - Overpass API

1. Extracción de datos

1. Extracción de datos

Implementa MapReduce

(computación paralela)

 

Análisis geoespacial distribuido

 

JavaScript + Mbtiles

1. Extracción de datos

Gestión de Tiles
Gestión resultados parciales y final

1. Extracción de datos

"MapReduce" 
versión "GEO"

reduce.js

Ejecución de operaciones y análisis 

map.js

Tile

resultado

Definir BBOX y path a MBTILES

1. Extracción de datos

reduce.js

const opts = {
    bbox: [-84.12, 9.9, -84.02, 9.96],
    log: true,
    zoom: 12,
    sources: [
      {
        name: 'osm',
        mbtiles: path.join(__dirname, 'data/latest.planet.mbtiles')      
      }
    ],
    maxWorkers: 4,
    map: __dirname+'/map.js'
};
.on('reduce', function(result, tile){
  num++;
  finalGeojson.features = finalGeojson.features.concat(result.features) ;
})

.on('end', function(error){
    (...)
});
Generar Geojson final solo con calles
module.exports = function(tileLayers, tile, writeData, done){

  const osmRoads = cleanGeoms(normalize(flatten(clip(tileLayers.osm.osm, tile))));
  done(null, osmRoads);

};
PASO 1:    Clip    +      flatten + normalize 

Turf.js

+

@mapbox/Tilebelt

1. Extracción de datos

map.js

geojson-flatten

+

geojson-normalize

turfjs.org

PASO 2: CleanGeoms

1. Extracción de datos

LineString
MultiLineString 
Polygon

?

module.exports = function(tileLayers, tile, writeData, done){

  const osmRoads = cleanGeoms(normalize(flatten(clip(tileLayers.osm.osm, tile))));
  done(null, osmRoads);

};

map.js

PASO 2: CleanGeoms

1. Extracción de datos

Polygon
module.exports = function(tileLayers, tile, writeData, done){

  const osmRoads = cleanGeoms(normalize(flatten(clip(tileLayers.osm.osm, tile))));
  done(null, osmRoads);

};

map.js

FIXED!

function isValidSquare(geom) {

  return (
    geom.geometry.type === 'Polygon' &&
    geom.properties.highway &&
    geom.properties.highway === 'pedestrian'&&
    geom.properties.area &&
    geom.properties.area === 'yes'
    && geom.properties.name !== undefined
  );

}
PASO 2: CleanGeoms

1. Extracción de datos

module.exports = function(tileLayers, tile, writeData, done){

  var osmRoads = cleanGeoms(normalize(flatten(clip(tileLayers.osm.osm, tile))));
  done(null, osmRoads);

};

map.js

PASO 2: CleanGeoms

1. Extracción de datos

 geom.properties = {
   name: geom.properties.name,
   id: geom.properties['@id'],
   wikipedia_link: '',
   gender: 'unknown',
   scale: ''
 };
module.exports = function(tileLayers, tile, writeData, done){

  var osmRoads = cleanGeoms(normalize(flatten(clip(tileLayers.osm.osm, tile))));
  done(null, osmRoads);

};

map.js

1. Extracción de datos

SOLUCIÓN: 
CLIP!

Calles fuera

del límite

1. Extracción de datos

CLIP:

OSM ID

Geojson Boundary 
flatten 
+ 
booleanContains
+

1. Extracción de datos

Calles fuera  

dentro del límite

1. Extracción de datos

Nombre "limpio" para clasificación

¿Cómo?

1. Extracción de datos

const filterList = ['Paseo','Río', 'Avenida', 'Hacienda', 'Puerto', 'Callejón', 'Calle', 'Calzada', 'Camino', 'Av.','Paso', 'Cañada', 'Minas', 'Cerrada', 
    'Puebla', 'Principal', 'Central','Primera', 'Segunda', 'Portón', 'Lateral', 'Calz.', 'Corrido', 'Casa', 'Villa', 'Mejía', 
    'Vía', 'Via', 'Real', 'Isla', 'Avendida', 'Marisma', 'Rada', 'Raudal', 'Ribera', 'Embocadura', 'Cataratas', 'Médanos', 
    'Mirador', 'Av', 'Jardín',  'A.', 'Circuito','Gral.', 'Rincón', 'Calz', 'Rinconada', 'Periférico', 'Cda', 'Jardin', 
    'C.', 'Callejon', 'Colegio', 'Valle', 'avenida', 'camino', 'calle', 'Calle', 'Rotonda', 'Parqueo', 'Parque', 'entrada', 
    'Entrada', 'sendero', 'Sendero', 'Pasaje', 'pasaje', 'Puerto', 'Ciudad', 'Puente', 'Boulevard', 'Agrosuperior', 'Bodegas', 
    'Autobanco', 'SkyTrace', 'Plaza', 'Motel', 'C/', 'Rotonda', 'Drive', 'Residencial', 'Automac', 
    'Auto', 'Transcersal', 'Inter', 'Pasillo', 'Centro', 'Caminito', 'Arandas', 'Proveedores', 'Cajero', 'Zona', 'Primer', 'Res.'
  ];

Diccionario

prefijos de tipos calles

idiomas!

1. Extracción de datos

1. Extracción de datos

RESULTADO FINAL:

  • nombreciudad_streets.geojson
  • list.csv

2. Tratar los datos

OBJETIVOS:

  • Clasificación de calles HOMBRE/MUJER
  • Asociar enlaces de Wikipedia
  • Revisión manual

SOLUCIÓN 1:

2. Tratar los datos

2.1. Clasificación F/M

Limitaciones de uso

Lento (petición/nombre)

Parseo "Nombre + Apellido"

API NameSor
API

SOLUCIÓN 2:

Listado CSV (fuente INE)

+25.000 nombres clasificados

Diccionario
local
github.com/marcboquet/spanish-names

2. Tratar los datos

2.1. Clasificación F/M

Cargar en memoria diccionarios

Coger nombre "limpio de CSV"

Jacint (Verdaguer)

Aparece en diccionario nombres mujer?

Aparece en diccionario nombres hombre?

NO
SI
es MUJER
SI
es HOMBRE
NO
Descartamos calle
new Set();

2. Tratar los datos

SOLUCIÓN 1:

2.2. Enlaces Wikipedia

Lenta (petición/calle)

Parseo resultado complejo

API de MediaWiki

2. Tratar los datos

SOLUCIÓN 2:

Wikidata
Wikiquote
Wikinoticas
Wikisource

68.000 entradas

2.2. Enlaces Wikipedia

2. Tratar los datos

SOLUCIÓN 2:

68.000 entradas

https://fusejs.io/

2.2. Enlaces Wikipedia

2. Tratar los datos

2.3. Revisión Manual

Las calles son de persona

Clasificación F/M

Enlaces a Wikipedia

2. Tratar los datos

nombreciudad_streets.geojson

¿Cómo?

Generar

GEOSJON FINAL

2. Tratar los datos

Generar

GEOSJON FINAL

const streeMap = new Map();

(...)

streeMap.set(splitLine[0], {
    url: url,
    gender: splitLine[4],
    scale: ""
});
var finalGeojson = {
    "type": "FeatureCollection",
    "features": []
};

for (var key in geojson.features) {

 if(streeMap.has(geojson.features[key].properties.name)){        
   (...)    
    finalGeojson.features.push(geojson.features[key]);
 }
}

2. Tratar los datos

Generar

ESTADÍSTICAS

if(!tratadosList.has(geojson.features[key].properties.name)){

  tratadosList.add(geojson.features[key].properties.name);

  if (objValues.url !== ('' && null && undefined) && objValues.gender.toLowerCase() === FEMALE){
    stats.numLink++;
    stats.numFemale++;
  }else if (objValues.gender.toLowerCase() === FEMALE){
    stats.numFemale++;
    stats.numNoLink++;                 
    noLinkList += `\n${geojson.features[key].properties.name}`;                                                             
  }else{
    stats.numMale++;
  }                    
}

2. Tratar los datos

GEOSJON FINAL Generado!

2. Tratar los datos

2. Tratar los datos

Problemas/errores conocidos.

  • Filtro por tipo HIGHWAY
  • Filtro por tipo LINESTRING (plazas)
  • BD de nombres incompleta
  • Criterios clasificación

3. Visor de datos

2. Visor de datos

    this.map = new mapboxgl.Map({
      container: 'map',
      style,
      center: initCenter, // [lng, lat]
      zoom: 1,
    });
Crear objeto mapa (MyMap.js)

2. Visor de datos

    map.addLayer({
      id: `${sourcename}-line`,
      type: 'line',
      source: {
        type: 'geojson',
        data: geojson,
      },
      layout: {
        'line-join': 'round',
        'line-cap': 'round',
      },
      paint: {
        'line-blur': ['case', ['==', ['get', 'wikipedia_link'], ''], 4, 1],
        'line-color': [
          'case',
          ['==', ['get', 'gender'], FEMALE],
          '#ffca3a',
          '#00B99E',
        ],
        'line-width': [
          'case',
          ['==', ['get', 'gender'], FEMALE],
          widthFemale,
          widthMale,
        ],
      },
    });
Añadir capa líneas:

2. Visor de datos

    map.addLayer({
      id: `${sourcename}-fill`,
      type: 'fill',
      source: {
        type: 'geojson',
        data: geojson,
      },
      layout: {},
      paint: {
        'fill-color': ['case', ['==', ['get', 'gender'], FEMALE], '#ffca3a', '#00B99E'],
        'fill-opacity': ['case', ['==', ['get', 'wikipedia_link'], ''], 0.2, 0.6],
      },
      filter: ['==', '$type', 'Polygon'],
    });
Añadir capa polígonos:

2. Visor de datos

Cómo añadir una nueva ciudad?

  1. Incluir resultados de los scripts en data
     
  2. Añadir ciudad en src/Constants.js
Constants.js
Ficheros resultado scripts

Datos hasta ahora

En la mayoría de ciudades, la proporción mujer-hombre está sobre el 15-85%

Y
Zaragoza?

Proyecto colaborativo

github.com/geochicasosm/

Intrucciones en README.md

https://geochicasosm.github.io/lascallesdelasmujeres/
https://github.com/geochicasosm

@geochicasosm

www.geochicas.org

Jessica Sena - @jsenag

#LasCallesDeLasMujeres Zaragoza 2020

By Jessica Sena

#LasCallesDeLasMujeres Zaragoza 2020

Las #CallesDeLasMujeres es un proyecto de ‘GeoChicasOSM’, que surgió en el marco del 8M de 2018. En la charla se explica el proceso técnico llevado a cabo para su realización, desde la obtención y tratamiento de los datos, hasta la elaboración del mapa para su visualización, haciendo hincapié en los problemas técnicos y limitaciones encontradas, y cómo se han solventado.

  • 744