Datos de las farmacias en la provincia de Valencia

Farmacias
Valencia
xlsx
Comunitat Valenciana
Autor/a
Afiliación

Natalia Vento Badía

Universitat de València

Fecha de publicación

17 de marzo de 2025

Input

Se ha obtenido un conjunto de datos de la Generalitat Valenciana (GVA) , disponible en este enlace, sobre las farmacias de la Comunitat Valenciana. Aunque los datos disponibles son sobre toda la comunidad autónoma, en este caso nos vamos a centrar únicamente en los establecimientos de la provincia de Valencia.

En este informe se va a documentar el proceso de obtención, limpieza y visualización de dicho conjunto de datos, tratando de corregir errores en direcciones y mejorar la geolocalización.

En primer lugar, vamos a instalar los paquetes y descargar las librerias necesarias:

# Librerías necesarias
libs <- c("readxl","tidyverse", "sf", "mapSpain", "osmdata", "tidygeocoder", "ggspatial", "curl", "leaflet", "dplyr", "openxlsx", "htmltools")
installed_libs <- libs %in% rownames(installed.packages())
if (any(installed_libs == F)) {install.packages(libs[!installed_libs])}
invisible(lapply(libs, library, character.only = T))

# Forzar conexión si hay problemas con la red
assign("has_internet_via_proxy", TRUE, environment(curl::has_internet))

Ahora leemos el conjunto de datos y filtramos por la provincia de Valencia. Para leer el archivo correctamente utilizamos skip = 1 ya que los nombres de las variables se encuentran en la segunda fila, por lo que ignoramos la primera fila.

df <- read_excel("data/000139/ListadoOficinasFarmacia.xlsx", skip = 1)

df <- df %>%
  filter(Provincia == "VALENCIA")

unique(df$Provincia)
[1] "VALENCIA"
head(df)
# A tibble: 6 × 8
  Establecimiento Provincia Municipio   Titular Dirección Departamento de Salu…¹
  <chr>           <chr>     <chr>       <chr>   <chr>     <chr>                 
1 V-353-F         VALENCIA  ADEMUZ      Mª ANT… AVDA VAL… 6                     
2 V-714-F         VALENCIA  ADOR        ERNEST… C/ JUAN … 12                    
3 V-512-F         VALENCIA  AGULLENT    MARIA … C/ TORRE… 14                    
4 V-1289-F        VALENCIA  AIELO DE M… ADELA … C/ MAJOR… 14                    
5 V-620-F         VALENCIA  AIELO DE M… JUAN A… AVDA SAN… 14                    
6 V-1081-F        VALENCIA  AIELO DE R… EVA MA… C/ JAIME… 12                    
# ℹ abbreviated name: ¹​`Departamento de Salud`
# ℹ 2 more variables: `Zona Sanitaria` <chr>, `Zona Farmacéutica` <chr>

Como podemos obervar, la base de datos no cuenta con las coordenadas geográficas de las farmacias. Para obtenerlas, vamos a utilizar la técnica del geocoding, empleando las variables referentes a la dirección de las farmacias, para obtener la longitud y latitud de cada establecimiento.

Descripción

Hemos detectado que la variable Dirección está compuesta por la calle, número y código postal de cada farmacia.

Para facilitar la geocodificación, vamos a dividir dicha variable en dos: calle y código postal. Esto permite una mejor normalización de los datos y ayuda a evitar errores en la asignación de coordenadas geográficas.

# Separamos la dirección en 2 partes: Calle y Código Postal
df <- df %>%
  mutate(Dirección = str_trim(Dirección)) %>%
  separate(Dirección, into = c("Direccion", "Codigo_Postal"), sep = ",\\s*(?=\\d{5}$)", extra = "merge", fill = "right")


# Limpiamos espacios en blanco extra
df <- df %>%
  mutate(across(everything(), str_trim))

head(df)
# A tibble: 6 × 9
  Establecimiento Provincia Municipio         Titular    Direccion Codigo_Postal
  <chr>           <chr>     <chr>             <chr>      <chr>     <chr>        
1 V-353-F         VALENCIA  ADEMUZ            Mª ANTONI… AVDA VAL… 46140        
2 V-714-F         VALENCIA  ADOR              ERNESTINA… C/ JUAN … 46729        
3 V-512-F         VALENCIA  AGULLENT          MARIA ANG… C/ TORRE… 46890        
4 V-1289-F        VALENCIA  AIELO DE MALFERIT ADELA CAS… C/ MAJOR… 46812        
5 V-620-F         VALENCIA  AIELO DE MALFERIT JUAN A. R… AVDA SAN… 46812        
6 V-1081-F        VALENCIA  AIELO DE RUGAT    EVA MARTI… C/ JAIME… 46842        
# ℹ 3 more variables: `Departamento de Salud` <chr>, `Zona Sanitaria` <chr>,
#   `Zona Farmacéutica` <chr>

Ahora, vamos a verificar que todos los códigos postales tengan cinco dígitos y correspondan a la provincia de Valencia. Esta verificación es esencial para garantizar la precisión de la geolocalización y evitar que farmacias de otras provincias sean incluidas erróneamente en el análisis.

# Verificamos si los códigos postales tienen exactamente 5 dígitos
df_5dig <- df %>% 
  filter(nchar(Codigo_Postal) != 5) %>% 
  select(Direccion, Codigo_Postal)

nrow(df_5dig)
[1] 0
#Verificamos que todos los códigos postales sean de la provincia de Valencia
df_valencia_invalidos <- df %>%
  filter(!str_starts(Codigo_Postal, "46"))

nrow(df_valencia_invalidos)
[1] 0

Y por último, vamos a crear una nueva variable que contenga la dirección completa de cada establecimiento: calle, número, municipio, provincia y país. Esto facilitará la geolocalización si empleamos para ello algunos métodos como arcgis.

df <- df %>%
  mutate(Direccion_Completa = paste(Direccion, Municipio, "VALENCIA, ESPAÑA", sep = ", "))

Empleamos la técnica de geocoding del paquete tidygeocoder:

crds <- geo(street = paste(df$Direccion),
             city = paste(df$Municipio),
             country = rep("Spain",nrow(df)),
             postalcode = df$Codigo_Postal)

Comprobamos cuántos valores faltantes hay en las variables que hacen referencia a las coordenadas, es decir, lat y long:

crds_na <- !is.na(crds$long) & !is.na(crds$lat)

sum(!crds_na)
[1] 208
crds[is.na(crds$lat) | is.na(crds$long), ]
# A tibble: 208 × 6
   street                                 city    postalcode country   lat  long
   <chr>                                  <chr>   <chr>      <chr>   <dbl> <dbl>
 1 C/ JUAN XXIII, 7                       ADOR    46729      Spain      NA    NA
 2 C/ JAIME I, 8                          AIELO … 46842      Spain      NA    NA
 3 CTRA ALDAYA, 9                         ALAQUAS 46970      Spain      NA    NA
 4 C/ SANTISIMO CRISTO DE LAS CAMPANAS, 8 ALBALA… 46687      Spain      NA    NA
 5 C/ PADRE SALVADOR, 1                   ALBALA… 46135      Spain      NA    NA
 6 PL PURISIMA, 1                         ALBALA… 46591      Spain      NA    NA
 7 C/ RAMON Y CAJAL, 85                   ALBERIC 46260      Spain      NA    NA
 8 C/ RAMON Y CAJAL, 1                    ALBERIC 46260      Spain      NA    NA
 9 C/ ANTONIO LLORET, 49                  ALBERIC 46260      Spain      NA    NA
10 C/ PIROTECNIC LLUIS BRUNCHU, 24        ALCANT… 46293      Spain      NA    NA
# ℹ 198 more rows

Hemos obtenido un total de 208 NA’s, es decir, 208 farmacias que no se han podido geolocalizar con esta técnica.

Tratamiento

Dado que hay un número considerable de valores faltantes, vamos probar con otro método de geolocalización. Para facilitar el proceso, vamos a trabajar únicamente con los datos de las farmacias de las cuales no se han podido obtener las coordenadas.

fallidas <- crds%>%
  filter(is.na(crds$lat) | is.na(crds$long))

df_fallidas <- fallidas %>%
  left_join(df, by = c("street" = "Direccion", 
                      "city" = "Municipio", 
                       "postalcode" = "Codigo_Postal"))

Hemos empleado la función left_join ya que vamos a emplear la variable Direccion_Completa, que se encuentra en df, para utilizar la técnica de geocoding con el método arcgis.

crds_arcgis <- tidygeocoder::geocode(df_fallidas, address = Direccion_Completa, method = "arcgis")

# Borramos las variables duplicadas o innecesarias
crds_arcgis <- crds_arcgis %>%
  select(-lat...5, -long...6) %>%
  rename(lat = lat...14, long = long...15)

# Comprobamos que no hay valores faltantes
arcgis_na <- !is.na(crds_arcgis$long) & !is.na(crds_arcgis$lat)

sum(!arcgis_na)
[1] 0

Ahora que ya tenemos las coordenadas de todas las farmacias, vamos a incluirlas en un conjunto de datos que recopile toda la información (df_final):

df_completo <- df %>%
  left_join(crds, by = c("Direccion" = "street", "Municipio" = "city", "Codigo_Postal" = "postalcode"))

df_final <- df_completo %>%
  left_join(crds_arcgis %>% select(street, city, postalcode, lat, long), 
            by = c("Direccion" = "street", "Municipio" = "city", "Codigo_Postal" = "postalcode")) %>%
  mutate(
    lat = coalesce(lat.x, lat.y),  # Usa las coordenadas corregidas si hay NA
    long = coalesce(long.x, long.y)
  ) %>%
  select(-lat.x, -lat.y, -long.x, -long.y)  # Eliminar columnas duplicadas
mapa <- leaflet(data =df_final) %>%
  addTiles() %>%
  addMarkers(
    ~long, ~lat, 
    popup = ~paste0("<b>Dirección:</b> ", Direccion, "<br>",
                    "<b>Municipio:</b> ", Municipio, "<br>",
                    "<b>Titular:</b> ", Titular, "<br>"))
mapa

Ahora el problema es que hay puntos en el mapa que están fuera de la provincia de Valencia porque las coordenadas son erróneas. Por ejemplo, hay un marcador de una farmacia de Chiva (municipio de la provincia de Valencia) en la provincia de Alicante. En algunos casos, esto se puede deber a que el nombre de una calle donde se encuentra una farmacia existe en diversos municipios, por lo que dichas coordenadas erróneas podrían pertenecer a una ubicación con la misma dirección (calle y número) pero en un municipio diferente al que se encuentra en realidad dicha farmacia.

Para solventar este problema, vamos a definir manualmente las coordenadas de las farmacias que no están correctamente ubicadas.

# Definimos las coordenadas manuales para las filas específicas
crds_manuales <- list(
  fila_1132 = c(39.4723134, -0.346948918),
  fila_225 = c(39.0777694, -0.510916650),
  fila_502 = c(39.3623868, -0.459476414),
  fila_925 = c(39.4718692, -0.359089274),
  fila_916 = c(39.4764655, -0.353231016),
  fila_273 = c(39.6603766, -0.672310707),
  fila_252 = c(39.431830, -0.558351),
  fila_899 = c(39.4855464, -0.384265047),
  fila_1070 = c(39.470516, -0.394229),
  fila_261 = c(39.1691658, -0.258794427),
  fila_842 = c(39.492218, -0.373466),
  fila_994 = c(39.482019, -0.395603),
  fila_1106 = c(39.488511, -0.366069),
  fila_226 = c(39.081618, -0.515988),
  fila_1043 = c(39.458348, -0.344575),
  fila_750 = c(39.485404, -0.393810),
  fila_969 = c(39.475303, -0.369929),
  fila_758 = c(39.460257, -0.395830),
  fila_269 = c(39.166492, -0.257018))

# Asignamos las coordenadas manualmente a las filas correspondientes en df_final
df_final[c(1132, 225, 502, 925, 916, 273, 252, 899, 1070, 261, 842, 994, 1106, 226, 1043, 750, 969, 758, 269), c("lat", "long")] <- do.call(rbind, crds_manuales)

Durante este proceso, se ha detectado que algunas direcciones eran erróneas, posible motivo por el cuál las coordenadas de estas farmacias no eran las correctas. A continuación, corregiremos las direcciones incorrectas.

# Corregimos las direcciones incorrectas
correcciones_direcciones <- data.frame(
  fila = c(502, 261, 994, 1106, 269), 
  Direccion = c("CARRER MAJOR, 29", 
                "CARRER VALENCIA, 118", 
                "C/ DE RASCANYA, 3", 
                "CARRER D'ALBOCASSER, 38",
                "CARRER VALENCIA, 12"))

# Reemplazamos en df_final las direcciones incorrectas
df_final[correcciones_direcciones$fila, "Direccion"] <- correcciones_direcciones$Direccion

Output

Tras este proceso, hemos obtenido un dataframe que contiene las coordenadas de la ubicación de las farmacias de la provincia de Valencia. Podemos observar el resultado en el siguiente mapa:

mapa2 <- leaflet(data = df_final) %>%
  addTiles() %>%
  addMarkers(
    ~long, ~lat, 
    clusterOptions = markerClusterOptions(),  # Agrupar marcadores cercanos
    popup = ~paste0("<b>Dirección:</b> ", Direccion, "<br>",
                    "<b>Municipio:</b> ", Municipio, "<br>",
                    "<b>Titular:</b> ", Titular, "<br>")) %>%
  setView(lng = mean(df_final$long, na.rm = TRUE), 
          lat = mean(df_final$lat, na.rm = TRUE), 
          zoom = 8)

mapa2

Ahora que todas las coordenadas son correctas, comprobamos que el conjunto de datos es de tipo data.frame y lo guardamos en un archivo xlsx:

class(df_final)
[1] "tbl_df"     "tbl"        "data.frame"

Guardamos los datos anteriores en un archivo xlsx:

ruta <- "df_farmacias.xlsx"
write.xlsx(df_final, file = ruta)

Y también en formato GeoPackage:

df_sf <- st_as_sf(df_final, coords = c("long", "lat"), crs = 4326)
# Guardar en formato GeoPackage
st_write(df_sf, "farmacias_valencia.gpkg", delete_layer = TRUE)

El fichero generado con este procedimiento se puede descargar en formato xlsx de aquí, y en formato GeoPackage de aquí.



Proyectos de Innovación Educativa Emergente PIEE-2737007 y PIEE-3325394