# Cargamos las siguientes librerías (asumimos que ya estan instaladas):
library(sf) # Para el tratamiento de objetos espaciales
library(tidyverse) # para la limpieza, transformacion y represetnacion
library(knitr) # Para el renderizado de tablas via kable()
library(tidygeocoder) # Para la geocodificacion
library(mapSpain) # Para cargar el listado de municipios de España
library(leaflet) # Para la graficación
library(RColorBrewer) # Para paletas de coloresExpendurías de Tabaco y Timbre en España
Input
Se ha obtenido un conjunto de datos de del Ministerio de Hacienda relativo a la Red de Expendurías de Tabaco y Timbre del Estado, ofrecido por el Ministerio de Hacienda de España. Más concretamente, solamente se registran las expendedurías activas durante el instante en el que se descargó el archivo, que en este caso concreto es el 07 de marzo de 2026 a las 19:10 horas y 36 segundos. Aun así, se pueden obtener datos más recientes clickando aquí.
La página web indexada contiene los datos en dos formatos: en una web interactiva en la que te puedes mover por el mapa de España, y un fichero descargable en formato csv. Nosotros usaremos el segundo.
Descripción
Cargamos las librerías necesarias.
Una vez cargadas, leemos ahora el dataset y veamos su estructura.
# Lectura y vista del dataset
df <- read.csv("../data/2526020044/DatosEstancos.csv")Error in `read.table()`:
! no se permiten 'row.names' duplicados
El error aparecido nos indica que existe algo mal en la base de datos y, tras abrirla, descubrimos tres errores:
La primera fila no está formateada de manera correcta, ya que contiene el título de “Listado de expendedurías activas a 07 de marzo de 2026 - 19:10:39”. Esto impide su lectura correcta tanto como encabezado como con dato, por lo que deberá ser ignorada.
La segunda fila está vacía, su función es separar el título anteriormente mencionado del resto de datos.
El elemento separador no es una coma (,), sino el punto y coma (;), este parámetro debe ser indicado en la función.
Por ello, con saltar las dos primeras líneas y definir el punto y coma como separador debería ser suficiente.
df <- read.csv("../data/2526020044/DatosEstancos.csv", skip = 2, sep = ";")Una vez cargado el dataframe veamos si está leído correctamente o si tiene algun vacío.
Estanco Municipio Localidad Dirección
0 0 0 0
A primera vista puede parecer que no hay ningun valor faltante en la base de datos, sin embargo, echando un vistazo a la bbdd nos daremos cuenta de que existe una fila que debe ser eliminada del conjunto: se trata de la línea final, la cual no contiene información de ningún estanco en concreto, sino de más bien todos.
Efectivamente, la última línea solamente recoge el total de estancos, y su existencia puede desencadenar en errores de conteo y tratamiento posteriores, por lo que la borraremos.
# Borremos la última fila:
df <- df[-nrow(df),]Analicemos ahora la estructura de los datos y los posibles valores faltantes.
# Veamos el número de filas y de columnas del conjunto de datos:
dim(df)[1] 12549 4
Podemos ver que el dataframe contiene 12549 filas y 4 columnas. Esto quiere decir que se han registrado cuatro campos por cada uno de los 12549 estancos que hay en españa (si no nos hubiésemos dado cuenta del error en la última línea pensaríamos que hay 12550 estancos).
Veamos ahora su estructura:
| Estanco | Municipio | Localidad | Dirección |
|---|---|---|---|
| 370041 | ALARAZ | ALARAZ | C. LA RUA. 7 |
| 130204 | TOMELLOSO | TOMELLOSO | D. ANTONIO HUERTA 64 |
| 060055 | ALJUCEN | ALJUCEN | C. CACERES, 2 |
| 430121 | MONT-ROIG DEL CAMP | MIAMI PLAYA | BARCELONA. 122 |
| 020162 | TARAZONA DE LA MANCHA | TARAZONA DE LA MANCHA | CALLE GERVASIO HERREROS 3 |
| 330364 | LLANES | LLANES | CALLE ROMAN ROMANO 12 |
Se detecta que las cuatro variables anteriormente son las mencionadas:
Estanco: El número indicador del estanco, así como una clave primaria.
Municipio: El municipio donde se encuentra el estanco.
Localidad: La localidad donde se encuentra el estanco. Aparentemente es igual al municipio.
Direccion: Dentro del municipio y localidad, la dirección donde se encuentra el estanco.
Lo primero que salta a la vista es que hayan dos variables idénticas, pero realmente hay datos duplicados en la tabla?
| Estanco | Municipio | Localidad | Dirección | |
|---|---|---|---|---|
| 4 | 430121 | MONT-ROIG DEL CAMP | MIAMI PLAYA | BARCELONA. 122 |
| 12 | 120048 | ALCALA DE XIVERT | ALCOSSEBRE | AVENIDA DE VALENCIA 84 |
| 15 | 410469 | SEVILLA | VALDEZORRAS | CALLE LIEBRE 16 |
| 21 | 300240 | CEUTI | TORRAOS (LOS) | CONSTITUCION.TORRAOS. 4 |
| 28 | 040113 | CUEVAS DEL ALMANZORA | VILLARICOS | BARIA 1(L-3) |
| 30 | 100053 | BAÑOS DE MONTEMAYOR | BAÑOS | C. DEL BAÑO. 14 |
La respuesta es no, pues un municipio es una unidad administrativa y una localidad es una unidad poblacional, de manera que varias localidades pueden pertenecer al mismo municipio. Por ejemplo, las localidad de Valencia pertenece al municipio de Valencia, pero también lo hacen las localidades de Perellonet, Palmar, Saler, Castellar-Oliveral o Masssarochos.
Una vez tenido en claro todo el contenido y estructura de la base de datos, pasemos a su tratamiento y mejora.
Tratamiento
En el apartado de Descripción ya se ha hecho un tratamiento previo, en tanto que habíamos de ignorar manualmente las dos primeras líneas de la tabla y cambiar el separador durante la lectura, así como hemos borrado la fila de totales tras la carga. Sin embargo, el dataset todavía tiene muchísimo más margen de mejora.
En primer lugar, lo más sensato sería añadir más niveles geográficos: estamos hablando de Provincia y Comunidad Autónoma.
Por ello, crearemos cinco nuevas columnas, las de PROVINCIA y CCAA, además del Código Postal, Código de Provincia, y Código de Comunidad Autónoma. Existen dos maneras de hacer esto:
Uniendo la tabla de datos de estancos con la de Municipios ofrecida por el paquete mapSpain a partir del municipio. Este procedimiento fue el inicialmente planteado para el tratamiento, pero contrajo tantos problemas (formateo de mayúsculas, espacios, tildes y nombres bilingües de ciudades) que al final ha sido descartado.
Geolocalizando a partir del municipio y dirección, y luego desgeolocalizando para obtener el resto de datos. Este método no solo es más sencillo, sino que además nos ofrecerá dos columnas extra muy valiosas: la longitud y latitud donde se encuentra el estanco. Aun así supone mucho más tiempo de computación.
Así pues, veamos si es eficaz la geolocalización.
# Añadimos variable auxiliar con el país = "ESPAÑA"
df$Pais <- "ESPAÑA"El largo proceso ha terminado, pero realmente ha cubierto todas las direcciones?
NAs lat NAs long
8 8
No, se nos han quedado ocho por determinar, veamos si con otro método (OpenStreetMap) las conseguimos cubrir.
# Intentamos por OpenStreetMap, para ello nos quedamos con las filas con NAs
pos_nas <- which(is.na(df_geo$lat))
df_geo[pos_nas,] <- df_geo[pos_nas,-c(6,7)] %>%
geocode(street = Dirección, city = Municipio, country = Pais,
method = "osm")
# Mostramos resultados
c("NAs lat" = sum(is.na(df_geo$lat)), "NAs long" = sum(is.na(df_geo$long))) NAs lat NAs long
4 4
No, todavía nos quedan cuatro. Si se tratara de más todavía podríamos obtener la API utilizar otro servicio de geocodificación e utilizarlo, pero para mayor replicabilidad del código y porque son muy pocos datos los introduciremos manualmente. Para ello se ha utilizado ayuda de Google Maps y de herramientas de IA.
# Buscamos las cuatro filas restantes
pos_nas <- which(is.na(df_geo$lat))
# Introducimos datos
df_geo[pos_nas, c(6,7)] <- data.frame("lat" = c(39.774917532426834, 39.89008951736611, 42.406420809923794, 42.818295665316604), "long" = c(3.0266723849928727, 4.267097749654371, 2.8735202890767693, 0.7108730094932885))
# Mostramos resultados
c("NAs lat" = sum(is.na(df_geo$lat)), "NAs long" = sum(is.na(df_geo$long))) NAs lat NAs long
0 0
Una vez conseguidos los datos, toca realizar codificación inversa para obtener diversos datos de cada estanco.
df_revgeo <- reverse_geo(lat = df_geo$lat, long = df_geo$long, method = "arcgis", full_results = T) # OTRAS DOS HORAS DE CODIFICACIÓNSe ha eliminado el ID del estanco, lo volvemos a insertar.
df_revgeo$Estanco <- df_geo$EstancoLos resultados de Arcgis nos han agregado 24 nuevas variables sobre cada estanco, pero si observamos los datos a primera vista nos damos cuenta de que puede que algunos estén vacíos con el carácter ““. Para ello calculemos el porcentaje de valores vacíos en cada columna:
# Calculamos el porcentaje de valores en ""
porc_nas <- colSums(df_revgeo == "")/nrow(df_revgeo) * 100
# Ponemos el dato redondeado y con porcentaje
porc_nas <- paste(round(porc_nas, 2), "%")
# Recuperamos nombres
names(porc_nas) <- names(df_revgeo)
# Mostramos resultados
kable(data.frame(porc_nas))| porc_nas | |
|---|---|
| lat | 0 % |
| long | 0 % |
| address | 0 % |
| Match_addr | 0 % |
| ShortLabel | 0 % |
| Addr_type | 0 % |
| Type | 31.22 % |
| PlaceName | 30.5 % |
| AddNum | 19.21 % |
| Address | 6.31 % |
| Block | 100 % |
| Sector | 100 % |
| Neighborhood | 80.59 % |
| District | 74.77 % |
| City | 0 % |
| MetroArea | 99.82 % |
| Subregion | 0 % |
| Region | 0 % |
| RegionAbbr | 0.26 % |
| Territory | 100 % |
| Postal | 0.26 % |
| PostalExt | 100 % |
| CntryName | 0 % |
| CountryCode | 0 % |
| X | 0 % |
| Y | 0 % |
| InputX | 0 % |
| InputY | 0 % |
| StrucType | 100 % |
| StrucDet | 100 % |
| Estanco | 0 % |
En general las nuevas variables que hemos conseguido son bastante completas, pero hay algunas de ellas que, o bien no contienen ningun dato, o bien son duplicadas de otras columnas.
Más concretamente, las columnas Block, Sector, MetroArea, Territory, PostalExt, StrucType y StrucDet cumplen el primer criterio, en el sentido de que todas sus filas solamente contienen el campo ““.
Por otro lado, las columnas InputX e InputY muestran las coordenadas de latitud y longitud que hemos pasado a Arcgis. Por tanto, coinciden casi en su totalidad con las columnas de lat y long, y cuando no lo hacen es por error de redondeo.
En cuanto a X e Y, los valores son extremadamente similares también a lat y long, debido a que son valores recalculados por ArcGIS. Por precaución(y porque la base de datos es relativamente perqueña) los dejaré estar, pero no puedo decir lo mismo del resto de datos:
Me guardaré mis comentarios sobre el resto de variables para el apartado de Output. Hasta entonces solo veo algunos últimos pasos a hacer en la base de datos: el primero sería cambiar los valores nulos (actualmente indicados con el carácter ““) por valores NAs.
# Sustituimos "" por NA
df_revgeo[df_revgeo == ""] <- NAEl segundo sería crear dos columnas nuevas, con el código de la província y de la CCAA, con la ayuda del Código Postal ya obtenido y el paquete mapSpain.
# Creamos columna código província:
df_revgeo <- df_revgeo %>%
mutate(cpro = str_sub(Postal,1,2))
# Sacamos tabla auxiliar con los códigos de las CCAAs
provs <- esp_get_prov()
# Unificamos crs
provs <- st_transform(provs, crs = 4326)
# Añadimos el código de la autonomía
df_revgeo <- df_revgeo %>%
left_join(select(st_drop_geometry(provs), codauto, cpro), by = "cpro")El tercer paso es arreglar las columnas de província (Subregion) y CCAA (Region), ya que en ocasiones se confunde la forma nacional y regional de llamarlas: por ejemplo, la provincia de Castellón aparece tanto como Castellón, así como Castelló e incluso Castellò. Así pues, nos quedaremos con las denominaciones ofrecidas por el Instituto Nacional de Estadística (INE) gracias nuevamente el paquete mapSpain.
# Añadimos el nombre de provincia ofrecido por el INE
df_revgeo <- df_revgeo %>%
left_join(select(st_drop_geometry(provs), cpro, ine.prov.name), by = "cpro")
# Añadimos el nombre de CCAA ofrecido por el INE
ccaas <- esp_get_ccaa()
# Unificamos CRS
ccaas <- st_transform(ccaas, crs = 4326)
df_revgeo <- df_revgeo %>%
left_join(select(st_drop_geometry(ccaas), codauto, ine.ccaa.name), by = "codauto")
# Renombramos columnas
df_revgeo <- df_revgeo %>%
rename(provincia = ine.prov.name,
ccaa = ine.ccaa.name)
# Ya no nos hace falta Subregion ni region, las eliminamos:
df_revgeo <- select(df_revgeo, -c(Subregion, Region))Finalmente, añadiremos la geometría de cada estanco, usando como Sistema de Coordenadas de Referencia (CRS) el formato global WGS84.
Además, prepararemos dos tablas agregadas con datos interesantes, que pueden ser objeto de estudios futuros:
Una con el número de estancos por provincia.
Una con el número de habitantes por estanco, por municipios.
La primera es el resultado del análisis más básico que podemos imaginar.
# Estancos por provincia
sumaprov <- df_final %>%
group_by(provincia, cpro) %>%
summarise(num_estancos = n())
sumaprov <- st_drop_geometry(sumaprov) %>%
left_join(select(provs, cpro, geometry), by = "cpro")
# Eliminamos datos faltantes
sumaprov <- sumaprov %>%
filter(!is.na(provincia))
sumaprov <- st_as_sf(as.data.frame(sumaprov))La segunda es más el resultado de mi curiosidad cuando tuve que imputar manualmente las latitudes y longitudes faltantes manualmente. Una de las expendedurías se encontraba en la localidad de Les, y tras buscar en Google Maps la ubicación para extraer la latitud y longitud del estanco, me chocó que este pueblo de poco más de 1000 habitantes llegara a tener 7 estancos en total. Mi propuesta, pues, es calcular un ratio de habitantes por estanco, de manera puramente exploratoria.
No obstante, como la columna de población por municipios ofrecida por el paquete mapSpain está vacía, recurriremos a la lectura del csv de datos de población por municipio elaborado por el Instituto Nacional de Estadística (INE). Más concretamente, usaremos los datos más recientes, relativos al año 2025.
# Extraemos tabla de municipios
munic <- esp_get_munic()
# Unificamos crs
munic <- st_transform(munic, crs = 4326)
# Sacamos estadísitca de poblacion por municipios
pob <- read.csv("https://www.ine.es/jaxiT3/files/t/csv_bdsc/29005.csv", sep = ";")
# Nos sacamos los datos más recientes y totales:
pob <- pob %>%
filter(Periodo == 2025 & Sexo == "Total")
# Borramos columnas periodo y sexo
pob <- pob %>%
select(-c(Sexo,Periodo))
# Transformamos a numerica la variable total
pob$Total <- gsub("\\.","", pob$Total)
pob$Total <- as.numeric(pob$Total)
# Dividimos nombre del municipio y CP
pob <- pob %>%
separate(Municipios, into = c("LAU","Nombre"), sep = " ", extra = "merge")
# Unimos datos municipales y de estancos por geometría
ratios <- st_join(munic, df_final, join = st_intersects)
# Unimos con datos de población por código LAU
ratios <- ratios %>%
left_join(pob, by = c("LAU_CODE"="LAU"))
# Calculamos el ratio de habitantes por estanco y su escala logarítmica. Este último porque tiene mejor visualización en gráficos (elimina el efecto de outliers canarios).
ratios <- ratios %>%
group_by(LAU_CODE) %>%
summarise(name = first(name), num_estancos = n(), Pob = first(Total), # Es constante para los pueblos por lo que no importa poner el primero
ratio = ifelse(num_estancos == 0, 0 ,round(Pob/num_estancos, 2)),
logratio = log(ratio))Como se puede comprobar en el código, se ha calculado el logaritmo del ratio de habitantes por estanco junto a este mismo ratio, esto es para una mejor visualización posterior de la Figura 3, en el apartado de Output.
Output
Se ha obtenido un dataset final con 23 variables acerca de los 12549 estancos de España. Esto supone un incremento notable desde las únicas cuatro originalmente proveídas. De ellas destacaremos las más importantes:
- Estanco: ID del estanco.
- X, Y: Latitud y longitud respectivas del estanco.
- geometry: Punto en el espacio que representa la ubicación del estanco, utilizando el sistema de coordenadas de referencia WGS84.
- Address, Addr_Type, City, Postal, cpro, codauto, …: variables que permiten ubicar la dirección del estanco desde distintos niveles geográficos: municipio, província, CCAA, etc.
- PlaceName: Nombre del local.
- Type: Tipo del local. Toma el valor “Specialty Store” para estancos.
Con ellas, podemos realizar fácilmente estadísticas y estudios acerca de los estancos de España.
Ahora, no voy a pretender que mi procedimiento es perfecto. De hecho, hay varios errores:
- El más notable: ArcGis, a la hora de descodificar, ha ubicado locales en la dirección que no corresponden a estancos. Por ello, en PlaceName podemos encontrar nombres tales como “Toldos y Espartarería Lorilla” o “Pizzerías Carlos”. Esto se puede deber a una base de datos incorrecta o a imprecisiones en los procesos de geolocalización y desgeolocaclización. De hecho, dos estancos de Vera de Bidasoa aparecen en el dataframe final como una tienda de muebles y un local de comida local, ambos en la localidad de Urrugne, Francia. Por desgracia no hay nada que podemos hacer al respecto más allá de nuestras capacidades.
Ante la pregunta de si debemos fiarnos más de los servicios de ArcGis o del Ministerio de Hacienda de España, creo que es más sensato la última, por lo que creeremos aun así que hay un estanco en la ubicación. Es por ello que no he filtrado por Type == “Specialty Store”. En cualquier caso, el estanco o bien se encuentra en esa misma dirección o se encuentra extremadamente cerca de la ubicada, por lo que el análisis espacial no debería verse afectado.
- También hay una cantidad notable de datos faltantes, como hemos visto en el aparado de Tratamiento, las cuales se han trasladado al dataframe final:
# Calculamos el porcentaje de valores en ""
porc_nas2 <- colSums(is.na(df_final))/nrow(df_final) * 100
# Ponemos el dato redondeado y con porcentaje
porc_nas2 <- paste(round(porc_nas2, 2), "%")
# Recuperamos nombres
names(porc_nas2) <- names(df_final)
# Mostramos resultados
kable(data.frame(porc_nas2))| porc_nas2 | |
|---|---|
| direccion_completa | 0 % |
| Match_addr | 0 % |
| ShortLabel | 0 % |
| Addr_type | 0 % |
| Type | 31.22 % |
| PlaceName | 30.5 % |
| AddNum | 19.21 % |
| Address | 6.31 % |
| Neighborhood | 80.59 % |
| District | 74.77 % |
| City | 0 % |
| RegionAbbr | 0.26 % |
| Postal | 0.26 % |
| CntryName | 0 % |
| CountryCode | 0 % |
| X | 0 % |
| Y | 0 % |
| Estanco | 0 % |
| cpro | 0.26 % |
| codauto | 0.28 % |
| provincia | 0.28 % |
| ccaa | 0.28 % |
| geometry | 0 % |
Más concretamente, la variable Neighborhood presenta un 80.59% de datos faltantes, un 74.77 % para District, un 31.22 % para Type, 30.5 % para PlaceName, un 19.21 % para AddNum, un 6.31 % para Address y un 0.26 % para las variables de magnitudes geográficas a nivel municipal, provincial y autonómico.
Por suerte, las variables más importantes no presentan NAs o presentan muy pocos, y aquellas variables que presentan más NAs no ofrecen tanto espacio de estudio.
- Finalmente, existe una inconsistencia procedente de ArcGis acerca de valores en la variable City, donde a veces se utiliza la denominación castellana (Ej:Valencia), a veces la denominación regional (Ej: València) y a veces las dos (Ej: València/Valencia). También es inconsistente en cuanto al uso de mayúsculas. Lamentablemente no he podido solucinar este error, pues el dataframe de estancos identifica los municipios mediante el Código Postal, mientras que el resto de bases de datos auxiliares utiliza el código municipal LAU. Además, si cruzamos tablas geográficamente, en el sentido de “el punto del estanco se encuentra dentro del polígono del municipio”, no podemos hacer un full join, por lo que la unificación de nombre de municipios queda como tarea pendiente.
Lo mismo ocurre con CntryCode, pero para la potencial depuración de datos franceses he decidido no uniformizarla.
Este procedimiento sí se ha podido realizar en provincias y comunidades autónomas, donde se ha usado el valor de nombre ofrecido por el INE, y la base de datos posee más que suficientes herramientas para unificar los nombres de los municipios fácilmente en el futuro.
- Además, las tablas auxiliares omiten aquellos estancos cuyo Código Postal no ha sido desgeocodificado correctamente, pese a que se trate solamente del 0.26 % de los datos más los dos estancos clasificados incorrectamente como franceses.
De ellas, la de la suma de estancos por provincia capta cuatro variables acerca de cada una de las 52 provincias de España: su nombre utilizado por el INE, su código de provincia, el número total de estancos en la provincia y un multipolígono con la geometría provincial.
Por otra parte, la tabla con los ratios de habitantes por estanco en municipios españoles contiene siete campos relativos a 8132 municipios españoles: El código municipal LAU, su nombre (ofrecido por el INE), el número de estancos, el valor de población en la encuesta de 2025 también del INE, el ratio de habitantes por estanco en el municipio y el logaritmo neperiano de este último valor. Finalmente, cómo no, la geometría del municipio. Se ha calculado el logaritmo del ratio para que luego se pueda realizar una mejor visualización espacial en la parte posterior de este apartado, sin que outliers canarios distorsionen la escala de colores.
Ahora, a continuación podemos ver un visualizador de los estancos en España, junto al nombre proveído por ArcGis, en caso de que se haya encontrado uno.
# Cambiamos NAs por "Nombre no encontrado"
df_final %>%
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
addCircleMarkers(popup = ~paste(Estanco, "<br>", PlaceName),
color = "red",
stroke = 2,
radius = 8,
clusterOptions = markerClusterOptions())Figura 1 Mapa interactivo con los estancos de España.
A su vez, las tablas auxiliares nos permiten hacer estudios como los siguientes:
# 1. Crear paleta de colores
pal <- colorNumeric(
palette = "YlOrRd", # paleta secuencial
domain = sumaprov$num_estancos
)
# 2. Mapa de coropletas
leaflet(sumaprov) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(
fillColor = ~pal(num_estancos),
weight = 1,
color = "white",
fillOpacity = 0.8,
popup = ~paste("Provincia:", provincia, "<br>nº estancos: ", num_estancos)
) %>%
addLegend(
pal = pal,
values = ~num_estancos,
title = "Número<br>de estancos"
)Figura 2 Estancos por provincia de España.
# 1. Crear paleta de colores
pal2 <- colorNumeric(
palette = "YlOrRd",
domain = ratios$logratio
)
# 2. Mapa de coropletas
leaflet(ratios) %>%
addProviderTiles("CartoDB.Positron") %>%
addPolygons(
fillColor = ~pal2(logratio),
weight = 1,
color = "white",
fillOpacity = 0.8,
popup = ~paste("Municipio:", name, "<br>Habitantes por estanco: ", ratio)
) %>%
addLegend(
pal = pal2,
values = ~logratio,
title = "Habitantes por<br>estanco (log)"
)Figura 3 Habitantes por estanco en municipios de España.
Sé que todavía queda mucho margen de mejora en este dataset, principalmente debido a la inexactitud de la geolocalización por el servicio ArcGis. Sin embargo, la base de datos por la que habíamos empezado era muy primitiva, quizás demasiado como para venir de un organismo tan importante como el Ministerio de Hacienda, y como además es una base de datos en constante actualización (los estancos se están dando de alta y baja continuamente), nada promete que en el futuro los problemas puedan ser otros.
De hecho, lo más sorprendente de esta base de datos es que como tal ya tienen el dato limpio en el ministerio, pues poseen dentro de la misma web un visor interactivo similar a la Figura 1, incluso indicando que han usado CRS WGS84, pero con el dato perfecto, y por algún motivo el csv que ofrecen al público es muchísimo más pobre.
Aun así, el objetivo de DataEnhance UV no es la de realizar un tratamiento perfecto del dato, sino la de mejorarlo, y con las limitaciones de tiempo y presupuestarias que han habido, estoy satisfecho con el resultado. De hecho, quizás este podría ser el punto de partida de otro proyecto, en el que se parta de este trabajo y se termine de perfeccionar la base de datos, quizás utilizando una API mejor freemium como la de Google, o encontrando una base de datos que permita intersectar por código postal.
Los ficheros generados con este procedimiento se pueden descargar de aquí.

Proyecto de Innovación Educativa Emergente (PIEE-3898312)