Primera versión del paquete climadiam para conectar con los servicios web del Subsistema de Climatología Ambiental (REDIAM). Permite consultar datos de estaciones meteorológicas de Andalucía de forma sencilla desde R.
El paquete permite conectarse al Subsistema CLIMA y facilita el acceso a datos meteorológicos y ambientales, incluyendo:
# Instalar 'climadiam' desde GitHub solo si no está instalado
list.of.packages <- c("climadiam")
new.packages <- list.of.packages[!(list.of.packages %in% installed.packages()[,"Package"])]
if(length(new.packages)) remotes::install_github(paste0("mcorzot/",new.packages))
# Cargar el paquete
library(climadiam)
user <- "usuario"
password <- "usuario"
idsesion <- getwsIDSesion(user, password)
estaciones <- getwsEstacionesList(idsesion)
head(estaciones)
## ACLPKACL AGEPKAGE CESTACION COMPKCOM COORDENADAX COORDENADAY COORDENADAZ
## text1 9 14 RIA18101 29 443423 4114357 630
## text2 6 18 IQ097 7 569900.49 4183241.37 1018
## text3 13 17 RAIFJA016 39 506412 4240315 515
## text4 15 12 SIVA36 43 430997 4181855 530
## text5 23 6 6049 50 299922.22 4046728 517
## text6 11 8 RIA4119 52 238128.73 4156064.04 11
## DENOMINACION ENTORNO ESTAPKESTA FECHAHORAPRO
## text1 IFAPA Centro Camino del Purchil <NA> 1 <NA>
## text2 Vélez-Blanco <NA> 1 <NA>
## text3 Arroyo del Ojanco <NA> 2 <NA>
## text4 Avda. DE MADRID <NA> 2 11/14/2025 8:30:0
## text5 Genalguacil <NA> 1 <NA>
## text6 IFAPA Centro Las Torres-Tomejil <NA> 1 <NA>
## FECHAHORAULTAGRE GESPKGES GRAFUBICACION LATITUD LONGITUD MODELO
## text1 <NA> 105 <NA> 37.172 -3.6385 A
## text2 <NA> 100 <NA> 37.792 -2.2073 A
## text3 8/8/2011 5:0:0 100 <NA> 38.309 -2.9279 A
## text4 5/22/2003 10:0:0 5 <NA> 37.7795 -3.7848 A
## text5 10/31/2001 0:0:0 5 <NA> 36.5431 -5.2364 P
## text6 <NA> 105 <NA> 37.5125 -5.964 A
## MUNMUNICIPIO MUNPROVINCIA OBSERVACION OBSERVACIONADM PKEST PLUVIO
## text1 87 18 <NA> <NA> 2865 <NA>
## text2 98 4 <NA> <NA> 3458 <NA>
## text3 905 23 <NA> <NA> 2892 <NA>
## text4 50 23 <NA> <NA> 2280 <NA>
## text5 57 29 <NA> <NA> 637 <NA>
## text6 5 41 <NA> <NA> 89 <NA>
## REDPKRED WEB
## text1 5 S
## text2 31 S
## text3 6 S
## text4 3 S
## text5 28 <NA>
## text6 5 S
datos <- getwsDatosDiarios(idsesion, "EARM22", "TD1", "26/10/2025")
head(datos)
## cestacion cvariable fecha valor
## 1 EARM22 TD1 26/10/2025 20.7
Obtención de fecha de ayer:
# Obtención de fecha a utilizar
date1 <- Sys.Date() - 1
date1_char <- format(date1, "%d/%m/%Y")
date1_char
## [1] "13/11/2025"
Obtención de fecha de antes de ayer:
# Obtención de fecha a utilizar
date2 <- Sys.Date() - 2
date2_char <- format(date2, "%d/%m/%Y")
date2_char
## [1] "12/11/2025"
Existencias de datos para la fecha de referencia (antes de ayer):
# Existencias de datos (tomando como referencia el día - 2)
existencias <- getwsDatosExisteEstacionesList(idsesion)
existencias$FECINICIODATOS <- as.Date(existencias$FECINICIODATOS)
existencias$FECFINDATOS <- as.Date(existencias$FECFINDATOS)
sel_existencias <- existencias[!is.na(existencias$CESTACION) & !is.na(existencias$FECINICIODATOS) & existencias$FECINICIODATOS < date2 & existencias$FECFINDATOS > date2, ]
head(sel_existencias[,c('CESTACION','FECINICIODATOS','FECFINDATOS')])
## CESTACION FECINICIODATOS FECFINDATOS
## 231 SIVA26 1996-06-05 2025-11-13
## 262 SIVA28 1998-01-31 2025-11-13
## 304 SIVA30 1997-12-22 2025-11-13
## 451 SIVA40 1996-01-01 2025-11-13
## 462 SIVA41 1996-01-02 2025-11-13
## 1254 RAIFAL001 1995-12-31 2025-11-13
Estaciones (teniendo en cuenta existencias):
# Características básicas de las estaciones seleccionadas
estaciones <- getwsEstacionesList(idsesion)
sel_estaciones <- estaciones[estaciones$CESTACION %in% sel_existencias$CESTACION, ]
head(sel_estaciones[,c('CESTACION','DENOMINACION','LATITUD','LONGITUD')])
## CESTACION DENOMINACION LATITUD LONGITUD
## text2 SIVA63 LAS FUENTEZUELAS 37.7844 -3.8103
## text4 RAIFMA006 Rincón de la Victoria 36.7128 -4.2488
## text11 RAIFJA003 Andújar 38.0339 -4.084
## text12 RAIFSE004 Isla Mayor 37.1771 -6.1806
## text13 SIVA51 SANTA CLARA 37.3981 -5.9514
## text23 RAIFSE008 El Saucejo 37.0731 -5.0902
Variables:
# Características de las variables seleccionadas
cvariables <- c("TI1", "PI1", "TD1", "TD2", "TD4","PD23")
variables <- data.frame()
for (cvariable in cvariables) {
sel_variables <- getwsVariables(cvariable, idsesion)
variables <- rbind(variables, sel_variables)
}
head(variables[,c('CVARIABLE','DENOMINACION')])
## CVARIABLE DENOMINACION
## text TI1 Temperatura media del termómetro seco
## text1 PI1 Precipitación caída en el período
## text2 TD1 Temperatura media diaria
## text3 TD2 Temperatura mínima diaria
## text4 TD4 Temperatura máxima diaria
## text5 PD23 Precipitación total diaria de 0 a 24
Se usa la función “getwsDatosIntradiariosMulti” que requiere los identificadores de los parámetros de la consulta
# Parámetros de la función
# estaciones del dataframe "sel_estaciones"
cvariables_int <- c("TI1","HI1")
fechas_int <- date1_char
# Se fragmenta la consulta por red para evitar saturar el servicio
datos_intradiarios1 <- data.frame() # Se crea dataframe en blanco para almacenar los datos
for (i in 1:length(unique(sel_estaciones$REDPKRED))) {
sel_estaciones_red <- sel_estaciones[sel_estaciones$REDPKRED == sel_estaciones$REDPKRED[i],]
sel_cestaciones <- sel_estaciones_red$CESTACION
sel_datos_intradiarios1 <- getwsDatosIntradiariosMulti(idsesion, sel_cestaciones, cvariables_int, fechas_int)
datos_intradiarios1 <- rbind(datos_intradiarios1,sel_datos_intradiarios1)
}
head(datos_intradiarios1)
## cestacion cvariable fecha hora valor
## 1 SIVA26 TI1 13/11/2025 00:00 17
## 2 SIVA26 TI1 13/11/2025 00:10 17
## 3 SIVA26 TI1 13/11/2025 00:20 17
## 4 SIVA26 TI1 13/11/2025 00:30 17
## 5 SIVA26 TI1 13/11/2025 00:40 17
## 6 SIVA26 TI1 13/11/2025 00:50 16
Se usa la función “getwsDatosIntradiariosMultiRaw” que requiere los identificadores internos de los parámetros de la consulta
# Obtener identificadores internos de las variables intradiarias
cvariables_int <- c("TI1","HI1")
variables <- getwsVariablesList(idsesion) # lista de todas las variables
sel_variables <- variables[variables$CVARIABLE %in% cvariables_int,]
pkvars_int <- sel_variables$PKVAR
# Obtener identificadores internos de las fechas
date1 <- Sys.Date() - 1
date1_char <- format(date1, format = "%d/%m/%Y")
fechas <- getwsFechasList(idsesion) # lista de todas las fechas
fecha <- fechas[fechas$FECHA == date1_char,]
pkfec_int <- fecha$PKFEC
pkfec_int_prev <- as.numeric(fecha$PKFEC) - 1 # pkfec del día previo
# Obtener identificadores internos de las estaciones
estaciones <- getwsEstacionesList(idsesion) # lista de todas las estaciones
sel_estaciones <- estaciones[estaciones$CESTACION %in% sel_existencias$CESTACION, ]
# Se descartan las estaciones PART003 y CAHA01 dado que el servicio falla al devolver datos con
# intervalos de medida inferiores a 10 minutos
sel_estaciones <- sel_estaciones[sel_estaciones$CESTACION != "PART003", ]
sel_estaciones <- sel_estaciones[sel_estaciones$CESTACION != "CAHA01", ]
# Consulta con la función "getwsDatosIntradiariosMultiRaw" y los identificadores internos
# Se obtienen datos del día objetivo y el día previo ya que en CLIMA el dato del día 1 a las 00:00
# se almacena como el dato de las 24:00 del día anterior
# Se fragmenta la consulta por red para evitar saturar el servicio
datos_intradiarios1_alt <- data.frame() # Se crea dataframe en blanco para almacenar los datos
for (red in unique(sel_estaciones$REDPKRED)) {
sel_estaciones_red <- subset(sel_estaciones, REDPKRED == red)
sel_pkests <- sel_estaciones_red$PKEST
# Consulta día previo
sel_datos_intradiarios1_alt_prev <- getwsDatosIntradiariosMultiRaw(idsesion,sel_pkests,pkvars_int,pkfec_int_prev)
# Consulta día objetivo
sel_datos_intradiarios1_alt <- getwsDatosIntradiariosMultiRaw(idsesion,sel_pkests,pkvars_int,pkfec_int)
# Se anexan los resultados
datos_intradiarios1_alt <- rbind(datos_intradiarios1_alt,sel_datos_intradiarios1_alt_prev,sel_datos_intradiarios1_alt)
}
head(datos_intradiarios1_alt)
## pkest pkvar pkfec minuto valor
## 1 2257 1 100758 NA NA
## 2 2257 1 100758 NA NA
## 3 2257 1 100758 NA NA
## 4 2257 1 100758 NA NA
## 5 2257 1 100758 NA NA
## 6 2257 1 100758 60 16.4
# Se borran los registros en blanco derivados de la estructura de la respuesta del servicio
datos_intradiarios1_alt <- datos_intradiarios1_alt[complete.cases(datos_intradiarios1_alt), ]
# Obtenidos los datos en bruto, se relacionan con las tablas maestras
# Se relaciona con las horas-minutos
datos_intradiarios1_alt <- merge(x = datos_intradiarios1_alt, y = minutos_horas, by.x='minuto', by.y='MINUTOS')
# Se convierte el dato de las 24:00 en el de las 00:00 del dia siguiente
datos_intradiarios1_alt$HORA[datos_intradiarios1_alt$HORA=="24:00"] <- "00:00"
datos_intradiarios1_alt$pkfec <- ifelse(datos_intradiarios1_alt$HORA %in% "00:00", as.character(as.integer(datos_intradiarios1_alt$pkfec)+1), datos_intradiarios1_alt$pkfec)
# Se filtra teniendo en cuenta la fecha indicada en la consulta
datos_intradiarios1_alt <- datos_intradiarios1_alt[datos_intradiarios1_alt$pkfec %in% pkfec_int,]
# Se borran duplicados si los hubiera
datos_intradiarios1_alt <- datos_intradiarios1_alt[!duplicated(datos_intradiarios1_alt), ]
# Se ordena el dataframe por hora
datos_intradiarios1_alt <- datos_intradiarios1_alt[order(datos_intradiarios1_alt$pkest,datos_intradiarios1_alt$pkvar,datos_intradiarios1_alt$pkfec,datos_intradiarios1_alt$HORA),]
# Se asocian los identificadores internos con los valores aportados en la funcion
datos_intradiarios1_alt <- merge(x = datos_intradiarios1_alt, y = estaciones, by.x = 'pkest', by.y = 'PKEST')
datos_intradiarios1_alt <- merge(x = datos_intradiarios1_alt, y = variables, by.x = 'pkvar', by.y = 'PKVAR')
datos_intradiarios1_alt <- merge(x = datos_intradiarios1_alt, y = fechas, by.x = 'pkfec', by.y = 'PKFEC')
# Se compone el dataframe
datos_intradiarios1_alt <- data.frame(datos_intradiarios1_alt$CESTACION,datos_intradiarios1_alt$CVARIABLE,datos_intradiarios1_alt$FECHA,datos_intradiarios1_alt$HORA,datos_intradiarios1_alt$valor)
colnames(datos_intradiarios1_alt) <- c('cestacion','cvariable','fecha','hora','valor')
head(datos_intradiarios1_alt)
## cestacion cvariable fecha hora valor
## 1 SIVA26 TI1 13/11/2025 00:00 17
## 2 SIVA26 TI1 13/11/2025 00:10 17
## 3 SIVA26 TI1 13/11/2025 00:20 17
## 4 SIVA26 TI1 13/11/2025 00:30 17
## 5 SIVA26 TI1 13/11/2025 00:40 17
## 6 SIVA26 TI1 13/11/2025 00:50 16
Se usa la función “getwsDatosDiariosMulti” que requiere los identificadores de los parámetros de la consulta
# Datos diarios
cestaciones <- sel_existencias$CESTACION
cvariables_dia <- c("TD1","TD2","TD4","PD23")
fechas_dia <- date2_char
datos_diarios2 <- getwsDatosDiariosMulti(idsesion, cestaciones, cvariables_dia, fechas_dia)
head(datos_diarios2)
## cestacion cvariable fecha valor
## 1 SIVA26 TD1 12/11/2025 18.0
## 2 SIVA55 TD1 12/11/2025 18.3
## 3 RAIFAL011 TD1 12/11/2025 15.9
## 4 RAIFGR003 TD1 12/11/2025 17.5
## 5 SIVA30 TD1 12/11/2025 18.4
## 6 SIVA59 TD1 12/11/2025 20.5
Se usa la función “getwsDatosDiariosMultiRaw” que requiere los identificadores internos de los parámetros de la consulta
# Obtener identificadores internos de las variables
cvariables_dia <- c("TD1","TD2","TD4","PD23")
variables <- getwsVariablesList(idsesion) # lista de todas las variables
sel_variables_dia <- variables[variables$CVARIABLE %in% cvariables_dia,]
pkvars_dia <- sel_variables_dia$PKVAR
# Obtener identificadores internos de las fechas
fechas_dia <- date2_char
date2_char <- format(date2, format = "%d/%m/%Y")
#fechas <- getwsFechasList(idsesion) # ejecutar sólo si no se hizo previamente
fecha <- fechas[fechas$FECHA == date2_char,]
pkfec_dia <- fecha$PKFEC
# Obtener identificadores internos de las estaciones
estaciones <- getwsEstacionesList(idsesion) # lista de estaciones
sel_estaciones <- estaciones[estaciones$CESTACION %in% sel_existencias$CESTACION, ]
# Se descartan las estaciones PART003 y CAHA01 dado que el servicio falla al devolver datos con
# intervalos de medida inferiores a 10 minutos
sel_estaciones <- sel_estaciones[sel_estaciones$CESTACION != "PART003", ]
sel_estaciones <- sel_estaciones[sel_estaciones$CESTACION != "CAHA01", ]
# Consulta con la función "getwsDatosDiariosMultiRaw" y los identificadores internos
# Fragmentar la consulta por red para evitar saturar el servicio
datos_diarios2_alt <- data.frame() # Se crea dataframe en blanco para almacenar los datos
for (red in unique(sel_estaciones$REDPKRED)) {
sel_estaciones_red <- subset(sel_estaciones, REDPKRED == red)
sel_pkests <- sel_estaciones_red$PKEST
# Consulta día objetivo
sel_datos_diarios2_alt <- getwsDatosDiariosMultiRaw(idsesion,sel_pkests,pkvars_dia,pkfec_dia)
# Se anexan los resultados
datos_diarios2_alt <- rbind(datos_diarios2_alt,sel_datos_diarios2_alt)
}
head(datos_diarios2_alt)
## pkest pkvar pkfec valor
## 1 2254 5 100758 26.1
## 2 2254 711 100758 0.0
## 3 2254 3 100758 13.0
## 4 2254 2 100758 19.5
## 5 2191 5 100758 24.5
## 6 2191 711 100758 0.0
# Se ordena el dataframe por estación, variable y fecha
datos_diarios2_alt <- datos_diarios2_alt[order(datos_diarios2_alt$pkest,datos_diarios2_alt$pkvar,datos_diarios2_alt$pkfec),]
# Se asocian los identificadores internos con los valores aportados en la funcion
datos_diarios2_alt <- merge(x = datos_diarios2_alt, y = estaciones, by.x = 'pkest', by.y = 'PKEST')
datos_diarios2_alt <- merge(x = datos_diarios2_alt, y = variables, by.x = 'pkvar', by.y = 'PKVAR')
datos_diarios2_alt <- merge(x = datos_diarios2_alt, y = fechas, by.x = 'pkfec', by.y = 'PKFEC')
# Se compone el dataframe
datos_diarios2_alt <- data.frame(datos_diarios2_alt$CESTACION,datos_diarios2_alt$CVARIABLE,datos_diarios2_alt$FECHA,datos_diarios2_alt$valor)
colnames(datos_diarios2_alt) <- c('cestacion','cvariable','fecha','valor')
head(datos_diarios2_alt)
## cestacion cvariable fecha valor
## 1 SIVA26 TD1 12/11/2025 18.0
## 2 SIVA55 TD1 12/11/2025 18.3
## 3 RAIFAL011 TD1 12/11/2025 15.9
## 4 RAIFGR003 TD1 12/11/2025 17.5
## 5 SIVA30 TD1 12/11/2025 18.4
## 6 SIVA59 TD1 12/11/2025 20.5
# Selección de las cuatro primeras series y crear una columna de fecha-hora combinada
cestaciones_graph <- unique(datos_intradiarios1_alt$cestacion)[1:4]
datos_int <- datos_intradiarios1_alt %>%
mutate(datetime = as.POSIXct(paste(fecha, hora), format = "%d/%m/%Y %H:%M")) %>%
filter(cestacion %in% cestaciones_graph & cvariable %in% c("TI1", "HI1"))
# Crear el gráfico de temperaturas intradiarias por estación
ggplot(datos_int, aes(x = datetime, y = valor, color = cvariable, group = cvariable)) +
geom_line(size = 1.2) +
geom_point(size = 2) +
facet_wrap(~ cestacion, scales = "free_y") +
labs(
title = "Evolución intradiaria de Temperatura (TI1) y Humedad (HI1)",
x = "Fecha y hora",
y = "Valor",
color = "Variable"
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5),
legend.position = "bottom"
)
# Selección de datos de TD2
datos_dia <- datos_diarios2_alt[datos_diarios2_alt$cvariable == 'TD2',]
# Histograma de frecuencias de datos de temperatura diaria
ggplot(datos_dia, aes(x = valor)) +
geom_histogram(binwidth = 1, fill = "#2b8cbe", color = "white", alpha = 0.8) +
labs(
title = "Distribución de valores de TD2",
x = "Valor de TD2",
y = "Frecuencia"
) +
theme_minimal(base_size = 13) +
theme(
plot.title = element_text(face = "bold", hjust = 0.5)
)
Desarrollado por mcorzot. Repositorio oficial: https://github.com/mcorzot/climadiam