Ideam_Logo

Estaciones hidrometeorológicas


Introducción

En este cuadernillo (Notebook) aprenderemos:

  1. Introduccion a la red de monitoreo del IDEAM

  2. Cátalogo de estaciones de IDEAM

  3. Consulta de datos usando la plataforma datosabiertos.gov.co

  4. Consulta de datos de temperatura y precipitación

  5. Otros datos disponibles

Prerequisitos

Conceptos

Importancia

Notas

Introducción a Pandas

Necesario

Lectura de datos tabulares

Introducción a Datetime

Necesario

Entender estampas de tiempo

Introducción a Cartopy

Necesario

Entender estampas de tiempo

Introducción a folium

Útil

Mapas interactivos

  • Tiempo de aprendizaje: 30 minutos

1. Catálogo nacional de estaciones de IDEAM

Según el catálogo de estaciones hidrometeorológicas del IDEAM, el país cuenta con alrededor de 4.400 estaciones de diferentes categorías. En el siguiente cuadro se resume el estado de las estaciones por categoría de acuerdo a la PQR No. 20229050190832 (Enero de 2023)

Categoría

Activa

Mantenimiento

Suspendidas

Limnográfica

287

109

106

Climátologica principal

215

60

92

Mareográfica

4

2

2

Pluviográfica

104

0

87

Limnométrica

323

11

557

Climática Ordinaria

211

31

253

Agrometeorológica

51

4

57

Radio Sonda

6

2

2

Pluviométrica

1109

9

603

Meteorológica Especial

40

4

68

Sinóptica Principal

27

3

4

Sinóptica Secundaria

2

0

5

Total

2381

235

1866

Librerías

A continuación vamos a importar las librerías que utilizaremos en este cuadernillo.

from datetime import datetime, timedelta

import cartopy.crs as ccrs
import cartopy.feature as feature
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib.dates import DateFormatter, HourLocator
from pandas import to_datetime

2. Acceso al catálogo en bart.ideam.gov.co

El catálogo nacional de estaciones del IDEAM actualizado se encuentra disponible en el servidor Bart. Podemos leer el catálogo usando pandas.read_excel como se muestra a continuación:

df_cat = pd.read_excel("http://bart.ideam.gov.co/cneideam/CNE_IDEAM.xls")
# df_cat.head()
df_cat.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 4493 entries, 0 to 4492
Data columns (total 21 columns):
 #   Column                Non-Null Count  Dtype         
---  ------                --------------  -----         
 0   OBJECTID              4493 non-null   int64         
 1   CODIGO                4493 non-null   int64         
 2   nombre                4493 non-null   object        
 3   CATEGORIA             4493 non-null   object        
 4   TECNOLOGIA            4493 non-null   object        
 5   ESTADO                4493 non-null   object        
 6   FECHA_INSTALACION     4492 non-null   datetime64[ns]
 7   altitud               4493 non-null   int64         
 8   latitud               4493 non-null   float64       
 9   longitud              4493 non-null   float64       
 10  DEPARTAMENTO          4493 non-null   object        
 11  MUNICIPIO             4493 non-null   object        
 12  AREA_OPERATIVA        4493 non-null   object        
 13  AREA_HIDROGRAFICA     4493 non-null   object        
 14  ZONA_HIDROGRAFICA     4493 non-null   object        
 15  observacion           1332 non-null   object        
 16  CORRIENTE             4493 non-null   object        
 17  FECHA_SUSPENSION      1844 non-null   datetime64[ns]
 18  SUBZONA_HIDROGRAFICA  4493 non-null   object        
 19  ENTIDAD               4493 non-null   object        
 20  subred                1143 non-null   object        
dtypes: datetime64[ns](2), float64(2), int64(3), object(14)
memory usage: 737.3+ KB

2.1 Mapa de estaciones

Podemos usar cartopy para hacer un mapa y visualizar las estaciones de monitoreo en el país

fig, ax = plt.subplots(subplot_kw={"projection": ccrs.PlateCarree()}, dpi=150)
ax.coastlines()
gl = ax.gridlines(draw_labels=True, crs=ccrs.PlateCarree())
ax.scatter(df_cat["longitud"], df_cat["latitud"], transform=ccrs.PlateCarree(), s=0.5)
ax.add_feature(feature.LAND)
ax.add_feature(feature.OCEAN)
ax.add_feature(feature.COASTLINE, linewidth=0.5)
ax.add_feature(feature.BORDERS, linewidth=0.5)
<cartopy.mpl.feature_artist.FeatureArtist at 0x7fb347bc6f50>
/usr/share/miniconda3/envs/atmoscol2023/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/50m_physical/ne_50m_land.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
/usr/share/miniconda3/envs/atmoscol2023/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/50m_physical/ne_50m_ocean.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
/usr/share/miniconda3/envs/atmoscol2023/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/50m_physical/ne_50m_coastline.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
/usr/share/miniconda3/envs/atmoscol2023/lib/python3.11/site-packages/cartopy/io/__init__.py:241: DownloadWarning: Downloading: https://naturalearth.s3.amazonaws.com/50m_cultural/ne_50m_admin_0_boundary_lines_land.zip
  warnings.warn(f'Downloading: {url}', DownloadWarning)
../../_images/e6f64b2c331a67a45105af8b64207cb4acb3918cfc49585db0dd4faaef1e65b3.png

podemos agrupar la data por área operativa, tipo de estación, tecnología, y otras variables

# df_grp = df_cat.groupby('AREA_OPERATIVA')
# df_grp = df_cat.groupby('TECNOLOGIA')
df_grp = df_cat.groupby("ESTADO")
fig, ax = plt.subplots(subplot_kw={"projection": ccrs.PlateCarree()}, dpi=150)

for _, group in df_grp:
    ax.scatter(
        group["longitud"],
        group["latitud"],
        transform=ccrs.PlateCarree(),
        s=0.5,
        label=_,
    )

ax.coastlines()
gl = ax.gridlines(draw_labels=True, crs=ccrs.PlateCarree())
ax.add_feature(feature.LAND)
ax.add_feature(feature.OCEAN)
ax.add_feature(feature.COASTLINE, linewidth=0.5)
ax.add_feature(feature.BORDERS, linewidth=0.5)
ax.legend(fontsize=5)
<matplotlib.legend.Legend at 0x7fb347bb14d0>
../../_images/c1ba67ee42f8e777e399aa351f4a819e4ed661afca95c6881e9eeeab15eee080.png

Podemos validar el número total de estaciones activas, en matenimiento y suspendidas de acuerdo con la información contenida en el catálogo

for grp in df_grp.groups.keys():
    print(f"{grp}: {len(df_grp.get_group(grp))}")
Activa: 2198
En Mantenimiento: 429
Suspendida: 1866

2.2 Mapa de estaciones interactivo

También podemos hacer mapas interactivos usando folium

import folium
from folium import plugins
from folium.plugins import MarkerCluster
min_lon, max_lon, min_lat, max_lat = -90, -72, -1, 14

map_ = folium.Map(
    location=[8, -76],
    zoom_start=6,
    min_lat=min_lat,
    max_lat=max_lat,
    min_lon=min_lon,
    max_lon=max_lon,
    zoom_control=False,
    control_scale=True,
    scrollWheelZoom=True,
    width=1000,
    height=600,
)
marker_cluster = MarkerCluster(name="Estaciones").add_to(map_)

folium.TileLayer("cartodbpositron").add_to(map_)
folium.TileLayer("openstreetmap").add_to(map_)
folium.TileLayer("cartodbdark_matter").add_to(map_)
folium.LayerControl().add_to(map_)

minimap = plugins.MiniMap()
_ = map_.add_child(minimap)

Ahora agregamos las estaciones usando la siguiente función:

def plot_station(row):
    """input: series that contains a numeric named latitude and a numeric named longitude
    this function creates a CircleMarker and adds it to your this_map"""

    html = row.to_frame("_").to_html(
        classes="table table-striped table-hover table-condensed table-responsive"
    )
    popup = folium.Popup(html, max_width=2650)
    folium.Marker(location=[row.latitud, row.longitud], popup=popup).add_to(
        marker_cluster
    )
df_cat.apply(plot_station, axis=1)
map_
Make this Notebook Trusted to load map: File -> Trust Notebook

3. Acceso a la información histórica de IDEAM usando datosabiertos.gov.co

la información histórica de múltiples sensores se puede consultar a través de la plataforma de datos abiertos usando el aplicativo sodapy. Socrata utiliza un módulo denominado Socrata que permite realizar consultas al repositorio. Cada variable hidrometeorógica dispuesta se puede consultar usando el su respectivo código del set de datos.

Variable

Código del set de datos

Dirección del viento

kiw7-v9ta

Nivel instantáneo

bdmn-sqnh

Temperatura Mínima del Aire

afdg-3zpb

Temperatura Máxima del Aire

ccvq-rp9s

Velocidad del Viento

sgfv-3yp8

Nivel Máximo

vfth-yucv

Nivel Mínimo

pt9a-aamx

Humedad del Aire

uext-mhny

Temperatura

sbwg-7ju4

Nivel del mar mínimo

7z6g-yx9q

Nivel del mar máximo

uxy3-jchf

Nivel del mar

ia8x-22em

Presión Atmosferica

62tk-nxj5

Precipitación

s54a-sgyg

# importamos la libreria Socrata
from sodapy import Socrata

3.1 Precipitación (s54a-sgyg)

Vamos a consultar los datos de precipitación reportada en la página, por ende vamos a usar el código s54a-sgyg. Para esto usamos el método Socrata, pasamos la dirección del repositorio y None que corresponde a la no autenticación

# conexión cliente usando socrata al repositorio de datos abiertos
client = Socrata("www.datos.gov.co", None)
WARNING:root:Requests made without an app_token will be subject to strict throttling limits.

Una vez creado el cliente empezamos a hacer la consulta de datos usando client.get y pasando los respectivos parámetros dataset_identifier, de la tabla anterior , y limit para generar consultas no muy grandes para efectos demostrativos. El resultado es una lista con múltiples diccionarios como se puede ver a continuación.

# Solicitud de informacion al repositorio de interés
results = client.get(dataset_identifier="s54a-sgyg", limit=2000)
results[:1]
[{'codigoestacion': '0021206940',
  'codigosensor': '0240',
  'fechaobservacion': '2008-12-31T22:20:00.000',
  'valorobservado': '0',
  'nombreestacion': 'CIUDAD BOLIVAR',
  'departamento': 'BOGOTA D.C.',
  'municipio': 'BOGOTA, D.C',
  'zonahidrografica': 'ALTO MAGDALENA',
  'latitud': '4.577',
  'longitud': '-74.177',
  'descripcionsensor': 'Precipitacion',
  'unidadmedida': 'mm'}]

Estos resultados los podemos convertir en un Dataframe usando pandas.Dataframe.from_records

results_df = pd.DataFrame.from_records(results)
results_df.head()
codigoestacion codigosensor fechaobservacion valorobservado nombreestacion departamento municipio zonahidrografica latitud longitud descripcionsensor unidadmedida
0 0021206940 0240 2008-12-31T22:20:00.000 0 CIUDAD BOLIVAR BOGOTA D.C. BOGOTA, D.C ALTO MAGDALENA 4.577 -74.177 Precipitacion mm
1 0024035250 0240 2019-05-31T21:40:00.000 0 CHITA - AUT BOYACÁ CHITA SOGAMOSO 6.188333333 -72.46633333 Precipitacion mm
2 0026137220 0240 2019-01-08T21:30:00.000 0 EL RETEN - AUT RISARALDA SANTA ROSA DE CABAL CAUCA 4.728194444 -75.60344444 Precipitacion mm
3 0024035390 0240 2008-07-10T12:30:00.000 1.6 PARAMO ALMORZADERO - AUT SANTANDER CERRITO SOGAMOSO 6.945388889 -72.69633333 Precipitacion mm
4 0013095010 0240 2016-07-28T12:00:00.000 0 COVEÑAS - DIMAR SUCRE TOLÚ CARIBE - LITORAL 9.383 -75.667 Precipitacion mm

Ahora podemos usar filtrar los datos por diferentes campos como el codigoestacion, fechaobservacion, o valorobservado. Podemos pasar parámetros SQL como where, AND, IN, entre otros, en el método client.get

# client.get?
# Solicitud de informacion para la estación de la Universidad Nacional - Bogotá - 0021205012
ppt_query = client.get(
    dataset_identifier="s54a-sgyg",
    select="fechaobservacion, valorobservado, codigoestacion",
    where="codigoestacion IN ('0021205012') \
                              AND fechaobservacion > '2017'",
)
df_est = pd.DataFrame.from_records(ppt_query)
df_est.head()
fechaobservacion valorobservado codigoestacion
0 2017-06-15T01:00:00.000 0 0021205012
1 2018-07-04T13:20:00.000 0 0021205012
2 2019-08-16T05:50:00.000 0 0021205012
3 2017-01-13T11:30:00.000 0 0021205012
4 2017-08-31T14:40:00.000 0 0021205012

Gráfico de la serie temporal

Podemos generar una serie temporal usando la información resultado de la consulta. Sin embargo, primero debemos revisar el tipo de dato de cada columna

df_est.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 3 columns):
 #   Column            Non-Null Count  Dtype 
---  ------            --------------  ----- 
 0   fechaobservacion  1000 non-null   object
 1   valorobservado    1000 non-null   object
 2   codigoestacion    1000 non-null   object
dtypes: object(3)
memory usage: 23.6+ KB
df_est["fechaobservacion"] = pd.to_datetime(df_est["fechaobservacion"])
df_est.set_index("fechaobservacion", inplace=True)
df_est.valorobservado = df_est["valorobservado"].astype(float)
df_est = df_est.sort_index()
df_est.tail()
valorobservado codigoestacion
fechaobservacion
2019-08-24 08:50:00 0.0 0021205012
2019-08-26 11:30:00 0.0 0021205012
2019-08-26 14:00:00 0.0 0021205012
2019-08-27 16:00:00 0.0 0021205012
2019-08-27 19:20:00 0.0 0021205012
# pd.options.plotting.backend = 'holoviews'
fig, ax = plt.subplots(figsize=(12, 3))
df_est["valorobservado"].plot(ax=ax, drawstyle="steps")
<Axes: xlabel='fechaobservacion'>
../../_images/a7194b3c4661a73dab5fb0bf5652578e1b4d7152d4382026f421344d0e6b4ea0.png

Podemos solicitar información para estaciones que reportan datos en el último mes

ppt_query = client.get(
    dataset_identifier="s54a-sgyg",
    select="fechaobservacion, valorobservado, codigoestacion, nombreestacion",
    where="fechaobservacion > '2023-09-11'",
)
df_ult = pd.DataFrame.from_records(ppt_query)
df_ult.head()
fechaobservacion valorobservado codigoestacion nombreestacion
0 2023-09-11T00:01:00.000 0 3502500135 GUAYABETAL POLLO OLIMPICO - AUT
1 2023-09-11T00:03:00.000 0 3502500135 GUAYABETAL POLLO OLIMPICO - AUT
2 2023-09-11T00:04:00.000 0 3502500135 GUAYABETAL POLLO OLIMPICO - AUT
3 2023-09-11T00:05:00.000 0 0026177030 LA VIRGINIA
4 2023-09-11T00:05:00.000 0 3502500135 GUAYABETAL POLLO OLIMPICO - AUT

3.2 Temperatura (sbwg-7ju4)

De manera similar podemos consultar otros registros como los de temperatura. Cambiamos el identificador de set de datos y generamos una nueva consulta

# Solicitud de informacion para la estación de la Universidad Nacional - Bogotá - 0021205012
temp_query = client.get(
    dataset_identifier="sbwg-7ju4",
    select="fechaobservacion, valorobservado, codigoestacion",
    where="codigoestacion IN ('0021205012') \
                              AND fechaobservacion > '2017'",
)
df_temp = pd.DataFrame.from_records(temp_query)
df_temp.index = pd.to_datetime(df_temp["fechaobservacion"])
df_temp.valorobservado = df_temp["valorobservado"].astype(float)
df_temp = df_temp.sort_index()
df_temp.tail()
fechaobservacion valorobservado codigoestacion
fechaobservacion
2020-01-22 08:00:00 2020-01-22T08:00:00.000 13.6 0021205012
2020-01-22 10:00:00 2020-01-22T10:00:00.000 18.1 0021205012
2020-01-22 12:00:00 2020-01-22T12:00:00.000 17.6 0021205012
2020-01-22 16:00:00 2020-01-22T16:00:00.000 17.7 0021205012
2020-01-22 21:00:00 2020-01-22T21:00:00.000 13.8 0021205012
fig, ax = plt.subplots(figsize=(12, 3))
df_temp["valorobservado"].plot(c="C00", lw=0.5, ax=ax)
<Axes: xlabel='fechaobservacion'>
../../_images/5bc434e1b88765f9dd77a72c02cef99ad83dde11a3e975fef143b028b5c04671.png

4. Datos en tiempo “Causi-real” de IDEAM

De igual manera, el IDEAM dispone de una tabla de datos en tiempo cercano a la medición. Esta tabla corresponde al dataset_identifier="57sv-p2fu". Generemos una consulta básica para ver los campos contenidos dentro de esta tabla en el último día

time_now = datetime.now()
time = time_now - timedelta(days=10)
time
datetime.datetime(2023, 11, 2, 20, 39, 54, 356837)

Convertimos la fecha en un str para incluirlo en la consulta

time_str = f"{to_datetime(time):%Y-%m-%d}"
time_str
'2023-11-02'
nrt_query = client.get(
    dataset_identifier="57sv-p2fu",
    select="*",
    where="fechaobservacion >= '{}'".format(time_str),
    limit=2000,
)
df_nrt = pd.DataFrame.from_records(nrt_query)
df_nrt.head()
codigoestacion codigosensor fechaobservacion valorobservado nombreestacion departamento municipio zonahidrografica latitud longitud descripcionsensor unidadmedida entidad
0 3502500135 0028 2023-11-11T23:06:00.000 100 GUAYABETAL POLLO OLIMPICO CUNDINAMARCA GUAYABETAL META 4.22553 -73.81481 GPRS - HUMEDAD DEL AIRE A 2 m % INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...
1 0029045190 0258 2023-11-11T23:04:00.000 1005.7 AEROPUERTO E. CORTISSOZ ATLANTICO SOLEDAD BAJO MAGDALENA 10.91777778 -74.77972222 GPRS - PRESIÓN ATMOSFÉRICA hPA INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...
2 0052055230 0257 2023-11-11T23:04:00.000 0 AEROPUERTO SAN LUIS NARIÑO ALDANA PATÍA 0.85708333 -77.67775 GPRS - PRECIPITACIÓN mm INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...
3 0017015010 0028 2023-11-12T14:06:00.000 74 AEROPUERTO SESQUICENTENARIO ARCHIPIÉLAGO DE SAN ANDRES PROVIDENCIA Y SANTA... SAN ANDRÉS ISLAS CARIBE 12.587849 -81.701117 GPRS - HUMEDAD DEL AIRE A 2 m % INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...
4 0028025090 0240 2023-11-12T08:00:00.000 0 CENTENARIO HACIENDA CESAR AGUSTÍN CODAZZI CESAR 9.85025 -73.26547222 PRECIPITACIÓN mm INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...

Los primeros registros nos indican que hay mediciones cercanas a las fechas de la ejecución de este cuadernillo. Generemos una consulta más específica para la estacion 0024035340 correspondiente al Aeropuerto Alberto Lleras Camargo de Sogamoso.

cod_est = "0024035340"
aero_query = client.get(
    dataset_identifier="57sv-p2fu",
    select="*",
    where="fechaobservacion >= '{}'\
                        AND codigoestacion IN ('{}')".format(
        time_str, cod_est
    ),
    limit=2000,
)
df_aero = pd.DataFrame.from_records(aero_query)
df_aero.head(10)
codigoestacion codigosensor fechaobservacion valorobservado nombreestacion departamento municipio zonahidrografica latitud longitud descripcionsensor unidadmedida entidad
0 0024035340 0028 2023-11-12T06:54:00.000 100 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 GPRS - HUMEDAD DEL AIRE A 2 m % INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...
1 0024035340 0257 2023-11-12T06:54:00.000 0 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 GPRS - PRECIPITACIÓN mm INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...
2 0024035340 0111 2023-11-12T06:54:00.000 0.8 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 GPRS - VELOCIDAD DEL VIENTO m/s INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...
3 0024035340 0071 2023-11-12T06:54:00.000 8.4 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 GPRS - TEMPERATURA DEL AIRE A 2 m °C INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...
4 0024035340 0257 2023-11-12T11:14:00.000 0 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 GPRS - PRECIPITACIÓN mm INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...
5 0024035340 0258 2023-11-12T11:14:00.000 759.2 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 GPRS - PRESIÓN ATMOSFÉRICA hPA INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...
6 0024035340 0104 2023-11-12T12:50:00.000 86 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 DIRECCIÓN DEL VIENTO GN INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...
7 0024035340 0111 2023-11-12T09:12:00.000 0.2 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 GPRS - VELOCIDAD DEL VIENTO m/s INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...
8 0024035340 0258 2023-11-12T06:54:00.000 758.9 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 GPRS - PRESIÓN ATMOSFÉRICA hPA INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...
9 0024035340 0258 2023-11-12T09:12:00.000 760 AEROPUERTO A LLERAS C BOYACÁ SOGAMOSO SOGAMOSO 5.67694444 -72.96791667 GPRS - PRESIÓN ATMOSFÉRICA hPA INSTITUTO DE HIDROLOGIA METEOROLOGIA Y ESTUDIO...

Para validar los sensores que tiene esta estacion podemo usar el método .unique() de Pandas

df_aero["codigosensor"].unique()
array(['0028', '0257', '0111', '0071', '0258', '0104', '0103', '0240',
       '0027', '0068', '0255', '0069', '0070'], dtype=object)

Podemos centrar aún mas la consulta agregándole el sensor de temperatura codigosensor=0071

cod_sensor = "0071"
aero_query = client.get(
    dataset_identifier="57sv-p2fu",
    select="fechaobservacion, valorobservado",
    where="fechaobservacion >= '{}'\
                        AND codigoestacion IN ('{}') \
                        AND codigosensor IN ('{}')".format(
        time_str, cod_est, cod_sensor
    ),
    limit=2000,
)
df_aero = pd.DataFrame.from_records(aero_query)
df_aero
fechaobservacion valorobservado
0 2023-11-12T06:54:00.000 8.4
1 2023-11-12T11:14:00.000 18.2
2 2023-11-12T06:56:00.000 8.5
3 2023-11-12T13:00:00.000 21.6
4 2023-11-12T11:16:00.000 18.2
... ... ...
714 2023-11-12T00:46:00.000 7.7
715 2023-11-12T00:48:00.000 7.8
716 2023-11-12T00:50:00.000 7.8
717 2023-11-12T00:52:00.000 7.6
718 2023-11-12T00:54:00.000 7.6

719 rows × 2 columns

Ahora generemos un gráfico rápido de la serie de temperatura para las últimas 24 horas

fig, ax = plt.subplots(figsize=(10, 3))
df_aero.index = pd.to_datetime(df_aero["fechaobservacion"])
df_aero.valorobservado = df_aero["valorobservado"].astype(float)
df_aero.plot(ax=ax)
ax.xaxis.set_major_locator(HourLocator(interval=4))  # tick every four hours
ax.xaxis.set_major_formatter(DateFormatter("%m-%d\n%H:%M"))
../../_images/caa7308a8344a92edeed2d069752abbc84c10468c3780d8a5bca76dbedbb8d66.png

Conclusiones

En este cuadernillo aprendimos una manera fácil y rápida como acceder a la información histórica y presente de las estaciones hidrometeorológicas del IDEAM. De igual modo aprendimos a visualizar las estaciones usando mapas interactivos. También aprendimos a generar consultas a diferentes grupos de datos usando sintaxis SQL y el aplicativo socrata de la plataforma de datos abiertos del gobierno Colombiano.

Resources and references

  • Rose, B. E. J., Kent, J., Tyle, K., Clyne, J., Banihirwe, A., Camron, D., May, R., Grover, M., Ford, R. R., Paul, K., Morley, J., Eroglu, O., Kailyn, L., & Zacharias, A. (2023). Pythia Foundations (Version v2023.05.01) https://doi.org/10.5281/zenodo.7884572