En este artículo, os mostramos un ejemplo práctico de análisis de datos mediante la librería Pandas de Python.
Veremos los distintos procesos que se requieren para llevar a cabo esta tarea, ya que no solo consiste en analizar los datos sino que abarca otros procesos igual de importantes como son la carga de los datos y limpiar los datos.
Estos dos procesos: obtención de los datos y limpieza de los mismos, son procesos que son necesarios también en el Machine Learning (de hecho suponen cerca del 80% del tiempo empleado).
Son procesos muy importantes y deben realizarse con cuidado ya que la calidad del resultado del análisis de datos o del modelo generado en el caso de Machine Learning dependen en gran medida de la calidad de los datos.
El artículo se ha realizado en un notebook de Jupyter para que tanto el código como la documentación esten en un mismo sitio.
El código puede ser ejecutado desde una terminal de forma normal (se puede extraer el código del notebook de forma sencilla desde la interfaz de Jupyter).
Para instalar Jupyter puede serguir las instrucciones indicadas en la web oficial o usando Docker. También se puede usar un servicio online si no se desea instalar nada.
Caso de estudio y objetivo del análisis de datos
Para nuestro ejemplo de análisis de datos utilizaremos los datos que provee la AEMET (Agencia estatal de Meteorología). Hemos usado los enlaces disponibles en su web ya que es mas sencilla su descarga.
Los datos contienen información diaria sobre temperatura (máxima, mínima y media), viento (racha y velocidad máxima de las medias) y precipitaciones (total y por tramo horario) para cada estación meteorológica de España.
En algunos casos falta información y eso se tiene que tener en cuenta durante el proceso de limpieza de datos.
Por simplificar el dataset, hemos realizado el análisis de datos únicamente del mes de Enero del año 2020.
Este artículo pretende ser simplemente un ejemplo de lo sencillo que es realizar operaciones sobre los datos mediante la librería Pandas y va a consistir en obtener ciertos valores para tener una visión del clima en las distintas provincias de España.
No pretende ser un análisis de datos completo de la información meteorológica del mes de Enero en España.
El artículo con los datos completos lo podéis encontrar aquí.
Introducción a Pandas y Python
Se va a usar el lenguaje Python ya que es probablemente el lenguaje más usado junto a R para el análisis científico de datos, así como para el Machine Learning.
En este ejercicio, hemos usado la versión 3 de Python.
Pandas es la es la librería de facto para el tratamiento y análisis de datos cuando usamos Python.
Nos proporciona la clase Dataframe la cual permite almacenar los datos en un objeto similar a una tabla de una base de datos.
Para ciertas tareas, hemos utilizado otras librerías de Python. Todas ellas se han instalado mediante el gestor de librerias de Python, pip.
Implementación y preparación del análisis de datos
A continuación desglosaremos paso a paso el ejercicio práctico. Si necesitas ayuda o quieres más información no dudes en ponerte en contacto con nosotros.
Importación de las librerias necesarias
En primer lugar, debemos importar las librerías que vamos a usar:
- Pandas: librería principal para la carga y el análisis de datos.
- Glob: librería para la gestión de ficheros. En nuestro caso se usa únicamente para realizar la carga de varios ficheros de forma más sencilla.
- Numpy: nos proporciona métodos de gestión de arrays.
#!pip install pandas
#!pip install numpy
import pandas as pd
import glob
import numpy as np
Carga de datos
Pandas nos permite obtener los datos de diversas fuentes, principalmente ficheros.
Además, podemos leer directamente de distintos formatos de fichero: xls, csv, json, etc. En nuestro caso leeremos ficheros xls.
Es importante también tener en cuenta que se puede escribir en el fichero el contenido de los datos, es decir, podemos leer los datos, modificarlos y escribirlos de nuevo en fichero. De esta forma podemos hacer procesos de modificación de datos de forma muy sencilla.
En nuestro caso, obtenemos los ficheros rar que contienen las hojas de cálculo con los datos. Cada fichero rar contiene los ficheros xls correspondientes a cada día de ese mes.
Para nuestro análisis de datos hemos cogido solo 1 mes (Enero), pero sería igual de sencillo cargar datos de otros meses.
!wget https://datosclima.es/capturadatos/Aemet2019-01.rar
--2020-07-09 18:10:33-- https://datosclima.es/capturadatos/Aemet2019-01.rar
Resolving datosclima.es (datosclima.es)... 95.217.108.87
Connecting to datosclima.es (datosclima.es)|95.217.108.87|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1456378 (1.4M) [application/x-rar-compressed]
Saving to: ‘Aemet2019-01.rar.9’
Aemet2019-01.rar.9 100%[===================>] 1.39M 3.00MB/s in 0.5s
2020-07-09 18:10:33 (3.00 MB/s) - ‘Aemet2019-01.rar.9’ saved [1456378/1456378]
# Instala unrar si es necesario
!unrar e -o+ Aemet2019-01.rar
UNRAR 5.50 freeware Copyright (c) 1993-2017 Alexander Roshal
Extracting from Aemet2019-01.rar
Extracting Aemet2019-01-22.xls 3 OK
Extracting Aemet2019-01-23.xls 6 OK
Extracting Aemet2019-01-24.xls 10 OK
Extracting Aemet2019-01-25.xls 1 13 OK
Extracting Aemet2019-01-26.xls 1 16 OK
Extracting Aemet2019-01-27.xls 1 19 OK
Extracting Aemet2019-01-28.xls 2 23 OK
Extracting Aemet2019-01-29.xls 2 26 OK
Extracting Aemet2019-01-30.xls 2 30 OK
Extracting Aemet2019-01-31.xls 3 33 OK
Extracting Aemet2019-01-01.xls 36 OK
Extracting Aemet2019-01-02.xls 39 OK
Extracting Aemet2019-01-03.xls 42 OK
Extracting Aemet2019-01-04.xls 45 OK
Extracting Aemet2019-01-05.xls 4 49 OK
Extracting Aemet2019-01-06.xls 5 52 OK
Extracting Aemet2019-01-07.xls 5 55 OK
Extracting Aemet2019-01-08.xls 5 58 OK
Extracting Aemet2019-01-09.xls 6 61 OK
Extracting Aemet2019-01-10.xls 6 64 OK
Extracting Aemet2019-01-11.xls 6 67 OK
Extracting Aemet2019-01-12.xls 6 70 OK
Extracting Aemet2019-01-13.xls 7 73 OK
Extracting Aemet2019-01-14.xls 7 76 OK
Extracting Aemet2019-01-15.xls 7 79 OK
Extracting Aemet2019-01-16.xls 8 82 OK
Extracting Aemet2019-01-17.xls 8 86 OK
Extracting Aemet2019-01-18.xls 8 89 OK
Extracting Aemet2019-01-19.xls 9 92 OK
Extracting Aemet2019-01-20.xls 9 96 OK
Extracting Aemet2019-01-21.xls 9 99 OK
All OK
Recorremos los ficheros xls ya descomprimidos y los vamos cargando en un objeto dataframe.
Si vemos el contenido de los ficheros xls podemos observar que no contienen la fecha de los datos, lo cual es un dato importante para nuestro análisis de datos porque queremos ordenar la información por fecha en algunos casos.
Para obtener este dato usaremos el nombre del fichero, el cual contiene la fecha a la que corresponden los datos. Vamos a incorporar una columa adicional al dataset con el nombre del fichero que estamos leyendo:
all_files = glob.glob("Aemet2019-*.xls")
file_list = []
for f in all_files:
data = pd.read_excel(f,skiprows=4)
data['source_file'] = f # nueva columna conteniendo el nombre del fichero leido
file_list.append(data)
df = pd.concat(file_list)
Vamos a ver cuantas filas y columnas contiene nuestro dataset:
df.shape
(24707, 13)
Podemos comprobar que tiene 24707 filas y 13 columnas.
A lo largo del artículo os iremos mostrando las 5 primeras filas y las 7 primeras columnas para ver cómo son los datos:
df.head()
Estación | Provincia | Temperatura máxima (ºC) | Temperatura mínima (ºC) | Temperatura media (ºC) | Racha (km/h) | Velocidad máxima (km/h) | |
---|---|---|---|---|---|---|---|
0 | Estaca de Bares | A Coruña | 11.2 (15:30) | 10.0 (03:40) | 10.6 | 64 (22:20) | 49 (22:20) |
1 | As Pontes | A Coruña | 10.7 (14:00) | 4.6 (05:30) | 7.6 | NaN | NaN |
2 | A Coruña | A Coruña | 13.1 (12:30) | 7.4 (02:40) | 10.3 | 41 (18:20) | 28 (15:40) |
3 | A Coruña Aeropuerto | A Coruña | 12.6 (15:50) | -0.8 (05:40) | 5.9 | 35 (15:20) | 23 (15:20) |
4 | Carballo, Depuradora | A Coruña | 11.6 (13:40) | -1.4 (03:20) | 5.1 | NaN | NaN |
Limpieza de datos
Una parte importante del proceso de obtención de datos es limpiar su contenido para que sea adecuado a nuestras necesidades y para hacerlos mas cómodos de usar.
Podemos empezar renombrando las columnas para que sea mas sencillo usarlas y ocupen menos espacio en pantalla.
df=df.rename(columns={'Estación': 'estacion','Provincia':'provincia','Temperatura máxima (ºC)':'temp_max','Temperatura mínima (ºC)':'temp_min','Temperatura media (ºC)':'temp_med','Racha (km/h)':'viento_racha','Velocidad máxima (km/h)':'viento_vel_max','Precipitación 00-24h (mm)':'prec_dia','Precipitación 00-06h (mm)':'prec_0_6h','Precipitación 06-12h (mm)':'prec_6_12h','Precipitación 12-18h (mm)':'prec_12_18h','Precipitación 18-24h (mm)':'prec_18_24h','source_file':'fecha'})
df.head(1)
estacion | provincia | temp_max | temp_min | temp_med | viento_racha | viento_vel_max | |
---|---|---|---|---|---|---|---|
0 | Estaca de Bares | A Coruña | 11.2 (15:30) | 10.0 (03:40) | 10.6 | 64 (22:20) | 49 (22:20) |
Observaremos que en algunas columnas además del valor numérico también se tiene la hora, lo cual no nos interesa ya que la información tiene que ser numérica para nuestro análisis de datos.
Así que vamos a quitar esa parte de los datos:
df=df.replace(to_replace=r'.(.+)$', value='', regex=True)
df.head(1)
estacion | provincia | temp_max | temp_min | temp_med | viento_racha | viento_vel_max | |
---|---|---|---|---|---|---|---|
0 | Estaca de Bares | A Coruña | 11.2 | 10.0 | 10.6 | 64 | 49 |
La columna que hemos creado para disponer del nombre del fichero y así disponer de la fecha de los datos contiene más texto además de la fecha.
Vamos a limpiar el valor para dejar solo la fecha:
df.fecha=df.fecha.replace(regex={'Aemet':'',r'.+xls':''})
df.head(1)
estacion | provincia | temp_max | temp_min | temp_med | viento_racha | fecha | |
---|---|---|---|---|---|---|---|
0 | Estaca de Bares | A Coruña | 11.2 | 10.0 | 10.6 | 64 | 2019-01-09 |
A continuación veremos de qué tipo son las columnas actualmente.
El tipo se puede definir explícitamente al leer el fichero, pero para este artículo hemos dejado que Pandas lo calcule de forma automática.
df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 24707 entries, 0 to 796
Data columns (total 13 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 estacion 24707 non-null object
1 provincia 24707 non-null object
2 temp_max 23650 non-null object
3 temp_min 23650 non-null object
4 temp_med 23650 non-null float64
5 viento_racha 20072 non-null object
6 viento_vel_max 20203 non-null object
7 prec_dia 23366 non-null float64
8 prec_0_6h 23565 non-null float64
9 prec_6_12h 23565 non-null float64
10 prec_12_18h 23584 non-null float64
11 prec_18_24h 23563 non-null float64
12 fecha 24707 non-null object
dtypes: float64(6), object(7)
memory usage: 2.6+ MB
Podemos observar que hay columnas con tipo «object» cuando debería ser un float (por ejemplo: temp_max y viento_racha).
Esto es porque hay filas que no tienen valor para esas columnas, luego veremos que hacer con ellas, por ahora vamos a poner los tipos adecuados a cada columna.
df=df.astype({'estacion': 'string','provincia': 'string', 'temp_max':'float64', 'temp_min':'float64', 'viento_racha':'float64', 'viento_vel_max':'float64','fecha': 'datetime64[ns]'})
df['fecha']=pd.to_datetime(df["fecha"].dt.strftime('%Y-%m-%d'))
df.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 24707 entries, 0 to 796
Data columns (total 13 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 estacion 24707 non-null string
1 provincia 24707 non-null string
2 temp_max 23650 non-null float64
3 temp_min 23650 non-null float64
4 temp_med 23650 non-null float64
5 viento_racha 20072 non-null float64
6 viento_vel_max 20203 non-null float64
7 prec_dia 23366 non-null float64
8 prec_0_6h 23565 non-null float64
9 prec_6_12h 23565 non-null float64
10 prec_12_18h 23584 non-null float64
11 prec_18_24h 23563 non-null float64
12 fecha 24707 non-null datetime64[ns]
dtypes: datetime64[ns](1), float64(10), string(2)
memory usage: 2.6 MB
Vamos a eliminar las estaciones que tienen filas a las que les faltan datos para estandarizar la información.
Realmente habría que intentar rellenar los datos que faltan mediante alguna de las técnicas recomendadas (media, propagate last valid observation forward, etc) pero para nuestro ejemplo vamos a simplemente eliminar filas por simplificar.
estaciones_con_nan=df[df.isnull().any(axis=1)]['estacion'].unique()
df.drop(df[df['estacion'].isin(estaciones_con_nan)].index, inplace=True)
df.isna().sum()
estacion 0
provincia 0
temp_max 0
temp_min 0
temp_med 0
viento_racha 0
viento_vel_max 0
prec_dia 0
prec_0_6h 0
prec_6_12h 0
prec_12_18h 0
prec_18_24h 0
fecha 0
dtype: int64
Análisis de datos
Ahora que ya tenemos los datos limpios vamos a empezar a analizarlos, demostrando que fácil es realizarlo con pandas.
Primeros contactos con los datos
Vamos a usar el método «describe» para ver de forma sencilla algunas medidas de nuestros datos.
También es un ejemplo de como podemos seleccionar ciertas columnas por su indice mediante el uso de la librería numpy.
df.iloc[:,np.r_[0:8,12:13]].describe()
temp_max | temp_min | temp_med | viento_racha | viento_vel_max | prec_dia | |
---|---|---|---|---|---|---|
count | 14663.000000 | 14663.000000 | 14663.000000 | 14663.000000 | 14663.000000 | 14663.000000 |
mean | 12.558869 | 2.557737 | 7.560342 | 34.010434 | 19.691741 | 1.490009 |
std | 4.506435 | 5.256177 | 4.350412 | 17.793154 | 11.139909 | 5.890856 |
min | -5.000000 | -20.500000 | -7.400000 | 0.000000 | 0.000000 | 0.000000 |
25% | 9.500000 | -1.300000 | 4.500000 | 20.000000 | 12.000000 | 0.000000 |
50% | 12.700000 | 2.100000 | 7.300000 | 30.000000 | 17.000000 | 0.000000 |
75% | 15.700000 | 5.900000 | 10.200000 | 45.000000 | 26.000000 | 0.000000 |
max | 27.800000 | 19.100000 | 21.100000 | 146.000000 | 113.000000 | 132.800000 |
Ahora vamos a mostrar 5 filas al azar como muestreo de los datos.
También es un ejemplo de selección de columnas por expresion regular (seleccionamos las que empiezan por el prefijo «temp_»)
df.filter(regex='^temp_*', axis=1).sample(5)
temp_max | temp_min | temp_med | |
---|---|---|---|
36 | 19.8 | 3.8 | 11.8 |
285 | 8.3 | 5.7 | 7.0 |
642 | 8.5 | -4.7 | 1.9 |
48 | 17.4 | 12.4 | 14.9 |
729 | 11.8 | 2.5 | 7.2 |
Medias por provincia
A continuación mostraremos la media de los valores de cada columna agrupándolos por provincia.
Podemos observar que el método es lo suficientemente inteligente para mostrarnos solo columnas de tipo numérico.
Os mostramos el contenido de las 4 primeras provincias (por orden alfabético) y de las 6 primeras columnas:
df.groupby('provincia').mean()
provincia | temp_max | temp_min | temp_med | viento_racha | viento_vel_max | prec_dia |
---|---|---|---|---|---|---|
A Coruña | 12.402765 | 5.505991 | 8.958065 | 43.552995 | 27.073733 | 3.329954 |
Alacant/Alicante | 15.780645 | 3.768664 | 9.777880 | 32.852535 | 18.253456 | 0.070968 |
Albacete | 12.548387 | -0.327419 | 6.117204 | 32.806452 | 17.376344 | 0.114516 |
Almería | 16.347312 | 7.915591 | 12.132258 | 40.731183 | 27.166667 | 0.101613 |
Mayores temperaturas máximas por estación
Vamos a mostrar los 3 valores mas altos de temperatura máxima que se han registrado en el mes.
Es un ejemplo de cómo ordenar por columna, mostramos solo las columnas que nos interesan y de esas columnas mostramos solo las primeras 3 filas.
df.sort_values(by='temp_max',ascending=False)[['fecha','estacion','provincia','temp_max']].head(3)
fecha | estacion | provincia | temp_max | |
---|---|---|---|---|
437 | 2019-01-13 | La Aldea de San Nicolás | Las Palmas | 27.8 |
427 | 2019-01-26 | Pájara | Las Palmas | 25.7 |
437 | 2019-01-01 | La Aldea de San Nicolás | Las Palmas | 25.6 |
Menores temperaturas mínimas por estación
De forma similar obtenemos los 3 valores más bajos de temperatura mínima.
df.sort_values(by='temp_min',ascending=True)[['fecha','estacion','provincia','temp_min']].head(3)
fecha | estacion | provincia | temp_min | |
---|---|---|---|---|
522 | 2019-01-21 | Villanueva de la Cañada | Madrid | -20.5 |
639 | 2019-01-06 | Cuéllar | Segovia | -12.1 |
763 | 2019-01-06 | Sardón de Duero | Valladolid | -11.8 |
Máximas diferencias entre temperatura max y min por provincia
Ahora calcularemos una nueva columna restando de la temperatura máxima la temperatura mínima.
Vemos que simplemente restamos columnas. Pandas es intuitivo.
df['diff_temp_min_max']=df['temp_max']-df['temp_min']
df.iloc[df.reset_index().groupby('provincia')['diff_temp_min_max'].idxmax()].sort_values(by='diff_temp_min_max',ascending=False)[['fecha','estacion','provincia','diff_temp_min_max','temp_min','temp_max']].head(10)
fecha | estacion | provincia | diff_temp_min_max | temp_min | temp_max | |
---|---|---|---|---|---|---|
522 | 2019-01-21 | Villanueva de la Cañada | Madrid | 30.9 | -20.5 | 10.4 |
763 | 2019-01-06 | Sardón de Duero | Valladolid | 26.6 | -11.8 | 14.8 |
639 | 2019-01-06 | Cuéllar | Segovia | 26.6 | -12.1 | 14.5 |
Mayores rachas de viento en un día por provincia
A continuación te mostramos un ejemplo de agrupar por una columna (provincia), obtener el máximo de los valores de otra columna (viento_racha) para cada grupo y ordenar posteriormente esas filas.
Todo se realiza en una sola línea.
df.iloc[df.reset_index().groupby('provincia')['viento_racha'].idxmax()].sort_values(by='viento_racha',ascending=False)[['fecha','estacion','provincia','viento_racha']].head(5)
fecha | estacion | provincia | viento_racha | |
---|---|---|---|---|
0 | 2019-01-29 | Estaca de Bares | A Coruña | 146.0 |
139 | 2019-01-29 | Machichaco | Bizkaia | 144.0 |
231 | 2019-01-27 | La Pobla de Benifassà-Fredes | Castelló/Castellón | 129.0 |
Mayores velocidades de viento medio en un día por provincia
De forma similar, hacemos el cálculo de las mayores velocidades de viento medio en un día por provincia.
df.iloc[df.reset_index().groupby('provincia')['viento_vel_max'].idxmax()].sort_values(by='viento_vel_max',ascending=False)[['fecha','estacion','provincia','viento_vel_max']].head(5)
fecha | estacion | provincia | viento_vel_max | |
---|---|---|---|---|
139 | 2019-01-23 | Machichaco | Bizkaia | 113.0 |
0 | 2019-01-29 | Estaca de Bares | A Coruña | 103.0 |
726 | 2019-01-28 | Andorra | Teruel | 82.0 |
Máximas velocidades de viento por provincia de media
Vemos un ejemplo de calcular una media por grupo de la forma mas fácil e intuitiva posible (con «group» y «mean»).
df.groupby('provincia').mean()[['viento_vel_max']].sort_values(by='viento_vel_max',ascending=False).head(5)
provincia | viento_vel_max |
---|---|
Castelló/Castellón | 27.669355 |
Almería | 27.166667 |
A Coruña | 27.073733 |
Máximas diferencias de temperatura máxima entre días
Te mostramos un ejemplo de cómo podemos hacer una operación (restar) entre la fila actual y la fila anterior de forma sencilla: con un «shift» desplazamos una columna hacia abajo.
df['temp_max_shifted']=df.groupby('estacion')['temp_max'].transform('shift')
df['dif_prev_temp_max']=df.temp_max-df.temp_max_shifted
df.iloc[df.reset_index().groupby('provincia')['dif_prev_temp_max'].idxmax()].sort_values(by='dif_prev_temp_max',ascending=False)[['fecha','estacion','provincia','dif_prev_temp_max']].head(5)
fecha | estacion | provincia | dif_prev_temp_max | |
---|---|---|---|---|
505 | 2019-01-01 | Rascafría | Madrid | 16.3 |
605 | 2019-01-01 | Velilla del Río Carrión, Camporredondo de Alba | Palencia | 15.5 |
470 | 2019-01-01 | Lagunas de Somoza | León | 14.5 |
Racha de días seguidos lloviendo por provincia y estación
El proceso de obtener rachas, es decir, número de días en los que pasa un suceso (en este caso llover) consecutivamente es un proceso algo más elaborado pero que se puede realizar en unas pocas líneas de código aprovechando las siguientes funcionalidades del dataframe:
- Creación de una nueva columna cuyo valor se obtiene a partir de otra columna aplicando una función lambda (cálculo de la columna «llueve»).
- Comparación de valores (operador «ne») entre columnas de una misma fila.
- Desplazamiento (método «shift») de una columna para disponer de datos anteriores en la misma fila.
- Generación de un número secuencial (identificador) de los elementos de cada grupo (método «cumsum»).
- Cálculo del número de elementos de un grupo (método «cumcount»).
- Asignación de un valor a una columna para las filas que cumplan una condición (llueve==0).
df['llueve']=df.prec_dia.apply(lambda x: 1 if x>0 else 0)
df.sort_values(by=['estacion','fecha'],ascending=True,inplace=True,ignore_index=True)
df['start_of_streak'] = df.llueve.ne(df['llueve'].shift())
df['estacion_anterior']=df['estacion'].shift()
df.loc[(df['estacion'].ne(df['estacion_anterior'])), 'start_of_streak'] = True
df['streak_id'] = df['start_of_streak'].cumsum()
df['dias_seguidos_lloviendo'] = df.groupby('streak_id').cumcount() + 1
df.loc[(df['llueve']==0), 'dias_seguidos_lloviendo'] = 0
df.iloc[df.reset_index().groupby(['provincia','estacion'])['dias_seguidos_lloviendo'].idxmax()].sort_values(by='dias_seguidos_lloviendo',ascending=False)[['estacion','provincia','dias_seguidos_lloviendo']].head(10)
estacion | provincia | dias_seguidos_lloviendo | |
---|---|---|---|
5083 | Elgeta | Gipuzkoa | 25 |
14631 | Zumarraga | Gipuzkoa | 20 |
5455 | Forua | Bizkaia | 18 |
Dónde llueve menos días seguidos por provincia y estación
Aprovechando la nueva columna «dias_seguidos_lloviendo» podemos sacar esta nueva métrica.
df.iloc[df.reset_index().groupby(['provincia','estacion'])['dias_seguidos_lloviendo'].idxmax()].sort_values(by='dias_seguidos_lloviendo',ascending=True)[['estacion','provincia','dias_seguidos_lloviendo']].head(10)
estacion | provincia | dias_seguidos_lloviendo | |
---|---|---|---|
7781 | Lorca, Zarcilla de Ramos | Murcia | 0 |
2542 | Belmonte | Cuenca | 0 |
12617 | Tazacorte | Santa Cruz de Tenerife | 0 |
Mostrar cuántas estaciones hay por provincia y un total general
Podemos tener copias «temporales» del dataframe para hacer operaciones sin destruir el original. Te lo ilustramos a través de este ejemplo.
Supongamos que queremos obtener el número de estaciones meteorológicas que hay por cada provincia.
Para ello nos quedamos con solo las columnas relevantes: provincia y estación. Luego eliminamos las filas duplicadas para tener los pares únicos de provincia-estación.
Ya nos queda simplemente agrupar por provincia y sacar el número de filas por cada grupo. Todo eso lo hacemos en 1 sola línea de código.
Finalmente añadimos otra fila adicional al resultado con el total de estaciones (un SUM típico de Excel).
df_estaciones=df[['provincia','estacion']].drop_duplicates().groupby('provincia').count()
df_estaciones.loc['Total de estaciones'] = df_estaciones['estacion'].sum()
df_estaciones
provincia | estacion |
---|---|
A Coruña | 7 |
Alacant/Alicante | 7 |
Albacete | 6 |
Almería | 6 |
Total de estaciones | 26 |
Conclusiones del análisis de datos
Hemos visto que es muy sencillo realizar tareas de carga de datos, limpieza de datos y extracción de información usando Pandas.
Las operaciones que haríamos en una base de datos (agrupar, calcular máximos y mínimos) e incluso algunas tareas más complejas como obtener rachas se hacen de forma sencilla, rápida y lo que es importante de forma programática.
Esto último es importante porque el código puede ser repositorizado, trackeado y ejecutado de forma automatizada.
Vemos también que se puede sacar información relevante de cualquier dataset. No es necesario llegar a usar algoritmos de Machine Learning para sacar provecho de la información disponible a la hora del análisis de datos.
La explotación de los datos mediante librerias como Pandas hace que podamos extraer información valiosa de forma sencilla y rápida, algo que es sumamente importante para cualquier empresa, entidad o incluso a nivel particular.
Podemos verlo como una mezcla entre Excel y SQL pero con las ventajas que hemos ido mostrando en este artículo.
Esperamos que os haya gustado este primer contacto con la liberia Pandas y estéis deseando probarla.
Es una librería ampliamente usada para las tareas de Machine Learning y Data Science pero es realmente útil para cualquier persona que tenga que tratar que realizar análisis de datos.
También esperamos que haya servido como primer contacto con los notebook de Jupyter, que son una herramienta increíble para tener en un mismo sitio el código y la documentación.
Además de que permiten compartirlo de forma sencilla y ser un punto de partida para la experimentación con el código contenido.