Jessica Sena
Software engineer. Design and development of web and mobile applications
Jessica Sena - @jsenag
#LasCallesDeGirona
Para conseguirlo:
Crear un mapa mundial.
Representar las calles con nombres de mujer y de hombre.
Enlazar cada calle de mujer con su artículo en Wikipedia
Identificar cuáles no tiene entrada
2. Tratamiento de datos
3. Generar el visor
1. Extracción de datos
OBJETIVO:
Obtener fichero con SÓLO las CALLES de una ciudad
Herramientas:
Tile Calculator - OSM QA Tiles - TileReduce
Implementa MapReduce
Análisis geoespacial distribuido
JavaScript + Mbtiles
Gestión de Tiles Gestión resultados parciales y final
"MapReduce" versión "GEO"
reduce.js
Ejecución de operaciones/Análisis
map.js
Tile
resultado
Definir BBOX y path a MBTILES
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){
var osmRoads = cleanLines(normalize(flatten(clip(tileLayers.osm.osm, tile))));
done(null, osmRoads);
};
PASO 1: Clip + flatten + normalize
Turf.js
+
@mapbox/Tilebelt
map.js
geojson-flatten
+
geojson-normalize
module.exports = function(tileLayers, tile, writeData, done){
var osmRoads = cleanLines(normalize(flatten(clip(tileLayers.osm.osm, tile))));
done(null, osmRoads);
};
PASO 2: CleanLines
map.js
LineString
Polygon
module.exports = function(tileLayers, tile, writeData, done){
var osmRoads = cleanLines(normalize(flatten(clip(tileLayers.osm.osm, tile))));
done(null, osmRoads);
};
PASO 2: CleanLines
map.js
module.exports = function(tileLayers, tile, writeData, done){
var osmRoads = cleanLines(normalize(flatten(clip(tileLayers.osm.osm, tile))));
done(null, osmRoads);
};
PASO 2: CleanLines
map.js
line.properties = {
name: line.properties.name,
id: line.properties['@id'],
wikipedia_link: '',
gender: 'unknown'
};
Nombre "limpio" para clasificación
var 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.'
];
prefijos de tipos calles
RESULTADO FINAL:
OBJETIVOS:
SOLUCIÓN 1:
Limitaciones de uso
Lento (petición/nombre)
Parseo "Nombre + Apellido"
API
SOLUCIÓN 2:
Listado CSV (fuente INE)
+25.000 nombres clasificados
Diccionario local
github.com/marcboquet/spanish-names
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();
SOLUCIÓN 1:
Lenta (petición/calle)
Parseo resultado complejo
API de MediaWiki
SOLUCIÓN 2:
Wikidata Wikiquote Wikinoticas Wikisource
68.000 entradas
SOLUCIÓN 2:
68.000 entradas
https://fusejs.io/
Las calles son de persona
Clasificación F/M
Enlaces a Wikipedia
nombreciudad_streets.geojson
¿Cómo?
Generar
GEOSJON FINAL
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]);
}
}
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++;
}
}
Problemas/errores conocidos.
map.addLayer({
"id": `${sourcename}`,
"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],
}
});
GeoJSON
VectorTiles?
github.com/geochicasosm/
Intrucciones en README.md
84% H / 16% M
84% H / 16% M
https://geochicasosm.github.io/lascallesdelasmujeres/ https://github.com/geochicasosm
@geochicasosm
www.geochicas.org
Jessica Sena - @jsenag
By Jessica Sena
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.
Software engineer. Design and development of web and mobile applications