Introducción a Pandas: análisis de datos
Introducción
Pandas es una biblioteca de Python diseñada específicamente para el análisis y manipulación de datos estructurados. Construida sobre NumPy, Pandas proporciona estructuras de datos flexibles y potentes herramientas que facilitan el trabajo con datos tabulares y series temporales. Es una herramienta imprescindible para científicos de datos, analistas y cualquier persona que necesite procesar, limpiar y analizar conjuntos de datos. En este artículo, exploraremos las estructuras de datos fundamentales de Pandas, así como las operaciones básicas para el análisis de datos.
Instalación de Pandas
Para comenzar a utilizar Pandas, primero debemos instalarlo:
pip install pandas
Importación de Pandas
Por convención, Pandas se importa con el alias pd
:
import pandas as pd
import numpy as np # También importamos NumPy, ya que suelen usarse juntos
Estructuras de datos principales
Pandas tiene dos estructuras de datos fundamentales:
Series
Una Series es un array unidimensional etiquetado, similar a una columna en una hoja de cálculo:
# Crear una Series desde una lista
s = pd.Series([10, 20, 30, 40])
print(s)
# 0 10
# 1 20
# 2 30
# 3 40
# dtype: int64
# Crear una Series con índices personalizados
s = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])
print(s)
# a 10
# b 20
# c 30
# d 40
# dtype: int64
# Crear una Series desde un diccionario
d = {'a': 10, 'b': 20, 'c': 30, 'd': 40}
s = pd.Series(d)
print(s)
# a 10
# b 20
# c 30
# d 40
# dtype: int64
Acceso a elementos de una Series
# Acceder por posición
print(s[0]) # 10
# Acceder por etiqueta
print(s['a']) # 10
# Acceder a múltiples elementos
print(s[['a', 'c']])
# a 10
# c 30
# dtype: int64
# Rebanado
print(s['a':'c'])
# a 10
# b 20
# c 30
# dtype: int64
DataFrame
Un DataFrame es una estructura de datos bidimensional etiquetada, similar a una tabla de base de datos o una hoja de cálculo:
# Crear un DataFrame desde un diccionario de listas
datos = {
'Nombre': ['Ana', 'Juan', 'María', 'Pedro'],
'Edad': [25, 30, 22, 40],
'Ciudad': ['Madrid', 'Barcelona', 'Sevilla', 'Valencia']
}
df = pd.DataFrame(datos)
print(df)
# Nombre Edad Ciudad
# 0 Ana 25 Madrid
# 1 Juan 30 Barcelona
# 2 María 22 Sevilla
# 3 Pedro 40 Valencia
# Crear un DataFrame desde una lista de diccionarios
personas = [
{'Nombre': 'Ana', 'Edad': 25, 'Ciudad': 'Madrid'},
{'Nombre': 'Juan', 'Edad': 30, 'Ciudad': 'Barcelona'},
{'Nombre': 'María', 'Edad': 22, 'Ciudad': 'Sevilla'},
{'Nombre': 'Pedro', 'Edad': 40, 'Ciudad': 'Valencia'}
]
df = pd.DataFrame(personas)
print(df) # Mismo resultado que el anterior
# Crear un DataFrame desde un array NumPy
array = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
df = pd.DataFrame(array, columns=['A', 'B', 'C'])
print(df)
# A B C
# 0 1 2 3
# 1 4 5 6
# 2 7 8 9
Propiedades del DataFrame
# Dimensiones (filas, columnas)
print(f"Forma: {df.shape}") # (3, 3)
# Nombres de columnas
print(f"Columnas: {df.columns}") # Index(['A', 'B', 'C'], dtype='object')
# Índices de filas
print(f"Índices: {df.index}") # RangeIndex(start=0, stop=3, step=1)
# Tipos de datos
print(f"Tipos de datos:\n{df.dtypes}")
# A int64
# B int64
# C int64
# dtype: object
# Información general
print(df.info())
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 3 entries, 0 to 2
# Data columns (total 3 columns):
# # Column Non-Null Count Dtype
# --- ------ -------------- -----
# 0 A 3 non-null int64
# 1 B 3 non-null int64
# 2 C 3 non-null int64
# dtypes: int64(3)
# memory usage: 200.0 bytes
# Resumen estadístico
print(df.describe())
# A B C
# count 3.000000 3.000000 3.000000
# mean 4.000000 5.000000 6.000000
# std 3.000000 3.000000 3.000000
# min 1.000000 2.000000 3.000000
# 25% 2.500000 3.500000 4.500000
# 50% 4.000000 5.000000 6.000000
# 75% 5.500000 6.500000 7.500000
# max 7.000000 8.000000 9.000000
Acceso a datos en un DataFrame
Hay varias formas de acceder a los datos en un DataFrame:
Selección de columnas
# Volvamos a nuestro DataFrame de personas
df = pd.DataFrame(datos)
# Seleccionar una columna (devuelve una Series)
nombres = df['Nombre']
print(nombres)
# 0 Ana
# 1 Juan
# 2 María
# 3 Pedro
# Name: Nombre, dtype: object
# Seleccionar múltiples columnas (devuelve un DataFrame)
info_personal = df[['Nombre', 'Edad']]
print(info_personal)
# Nombre Edad
# 0 Ana 25
# 1 Juan 30
# 2 María 22
# 3 Pedro 40
Selección de filas
# Usando .loc[] para seleccionar por etiqueta
fila_2 = df.loc[2]
print(fila_2)
# Nombre María
# Edad 22
# Ciudad Sevilla
# Name: 2, dtype: object
# Usando .iloc[] para seleccionar por posición
primera_fila = df.iloc[0]
print(primera_fila)
# Nombre Ana
# Edad 25
# Ciudad Madrid
# Name: 0, dtype: object
# Seleccionar múltiples filas
filas_1_3 = df.iloc[[0, 2]]
print(filas_1_3)
# Nombre Edad Ciudad
# 0 Ana 25 Madrid
# 2 María 22 Sevilla
# Rebanado de filas
filas_0_a_2 = df.iloc[0:2]
print(filas_0_a_2)
# Nombre Edad Ciudad
# 0 Ana 25 Madrid
# 1 Juan 30 Barcelona
Selección condicional
# Filtrar personas mayores de 25 años
mayores_25 = df[df['Edad'] > 25]
print(mayores_25)
# Nombre Edad Ciudad
# 1 Juan 30 Barcelona
# 3 Pedro 40 Valencia
# Filtrar personas de Madrid
de_madrid = df[df['Ciudad'] == 'Madrid']
print(de_madrid)
# Nombre Edad Ciudad
# 0 Ana 25 Madrid
# Combinar condiciones
filtro = (df['Edad'] > 25) & (df['Ciudad'] != 'Valencia')
print(df[filtro])
# Nombre Edad Ciudad
# 1 Juan 30 Barcelona
Operaciones básicas con DataFrames
Añadir y eliminar columnas
# Añadir una nueva columna
df['Profesión'] = ['Ingeniera', 'Médico', 'Profesora', 'Arquitecto']
print(df)
# Nombre Edad Ciudad Profesión
# 0 Ana 25 Madrid Ingeniera
# 1 Juan 30 Barcelona Médico
# 2 María 22 Sevilla Profesora
# 3 Pedro 40 Valencia Arquitecto
# Añadir una columna calculada
df['Año_Nacimiento'] = 2023 - df['Edad']
print(df)
# Nombre Edad Ciudad Profesión Año_Nacimiento
# 0 Ana 25 Madrid Ingeniera 1998
# 1 Juan 30 Barcelona Médico 1993
# 2 María 22 Sevilla Profesora 2001
# 3 Pedro 40 Valencia Arquitecto 1983
# Eliminar columnas
df_sin_profesion = df.drop('Profesión', axis=1)
print(df_sin_profesion)
# Nombre Edad Ciudad Año_Nacimiento
# 0 Ana 25 Madrid 1998
# 1 Juan 30 Barcelona 1993
# 2 María 22 Sevilla 2001
# 3 Pedro 40 Valencia 1983
# Eliminar múltiples columnas
df_basico = df.drop(['Profesión', 'Año_Nacimiento'], axis=1)
print(df_basico)
# Nombre Edad Ciudad
# 0 Ana 25 Madrid
# 1 Juan 30 Barcelona
# 2 María 22 Sevilla
# 3 Pedro 40 Valencia
Añadir y eliminar filas
# Añadir una fila usando .loc[]
df.loc[4] = ['Carlos', 35, 'Bilbao', 'Abogado', 1988]
print(df)
# Nombre Edad Ciudad Profesión Año_Nacimiento
# 0 Ana 25 Madrid Ingeniera 1998
# 1 Juan 30 Barcelona Médico 1993
# 2 María 22 Sevilla Profesora 2001
# 3 Pedro 40 Valencia Arquitecto 1983
# 4 Carlos 35 Bilbao Abogado 1988
# Concatenar DataFrames
nueva_persona = pd.DataFrame({
'Nombre': ['Laura'],
'Edad': [28],
'Ciudad': ['Zaragoza'],
'Profesión': ['Diseñadora'],
'Año_Nacimiento': [1995]
})
df = pd.concat([df, nueva_persona], ignore_index=True)
print(df)
# Nombre Edad Ciudad Profesión Año_Nacimiento
# 0 Ana 25 Madrid Ingeniera 1998
# 1 Juan 30 Barcelona Médico 1993
# 2 María 22 Sevilla Profesora 2001
# 3 Pedro 40 Valencia Arquitecto 1983
# 4 Carlos 35 Bilbao Abogado 1988
# 5 Laura 28 Zaragoza Diseñadora 1995
# Eliminar filas
df_sin_carlos = df.drop(4)
print(df_sin_carlos)
# Nombre Edad Ciudad Profesión Año_Nacimiento
# 0 Ana 25 Madrid Ingeniera 1998
# 1 Juan 30 Barcelona Médico 1993
# 2 María 22 Sevilla Profesora 2001
# 3 Pedro 40 Valencia Arquitecto 1983
# 5 Laura 28 Zaragoza Diseñadora 1995
# Reiniciar índices
df_reset = df_sin_carlos.reset_index(drop=True)
print(df_reset)
# Nombre Edad Ciudad Profesión Año_Nacimiento
# 0 Ana 25 Madrid Ingeniera 1998
# 1 Juan 30 Barcelona Médico 1993
# 2 María 22 Sevilla Profesora 2001
# 3 Pedro 40 Valencia Arquitecto 1983
# 4 Laura 28 Zaragoza Diseñadora 1995
Manejo de datos faltantes
En el análisis de datos reales, es común encontrar valores faltantes. Pandas proporciona herramientas para detectarlos y tratarlos:
# Crear un DataFrame con valores nulos
datos_incompletos = {
'A': [1, 2, np.nan, 4],
'B': [5, np.nan, np.nan, 8],
'C': [9, 10, 11, 12]
}
df_nulos = pd.DataFrame(datos_incompletos)
print(df_nulos)
# A B C
# 0 1.0 5.0 9
# 1 2.0 NaN 10
# 2 NaN NaN 11
# 3 4.0 8.0 12
# Detectar valores nulos
print(df_nulos.isnull())
# A B C
# 0 False False False
# 1 False True False
# 2 True True False
# 3 False False False
# Contar valores nulos por columna
print(df_nulos.isnull().sum())
# A 1
# B 2
# C 0
# dtype: int64
# Eliminar filas con valores nulos
print(df_nulos.dropna())
# A B C
# 0 1.0 5.0 9
# 3 4.0 8.0 12
# Eliminar columnas con valores nulos
print(df_nulos.dropna(axis=1))
# C
# 0 9
# 1 10
# 2 11
# 3 12
# Rellenar valores nulos
print(df_nulos.fillna(0)) # Reemplazar por cero
# A B C
# 0 1.0 5.0 9
# 1 2.0 0.0 10
# 2 0.0 0.0 11
# 3 4.0 8.0 12
# Rellenar con el valor anterior/siguiente
print(df_nulos.fillna(method='ffill')) # forward fill
# A B C
# 0 1.0 5.0 9
# 1 2.0 5.0 10
# 2 2.0 5.0 11
# 3 4.0 8.0 12
print(df_nulos.fillna(method='bfill')) # backward fill
# A B C
# 0 1.0 5.0 9
# 1 2.0 8.0 10
# 2 4.0 8.0 11
# 3 4.0 8.0 12
Operaciones estadísticas y agrupación
Estadísticas descriptivas
# Volvamos a nuestro DataFrame de personas
print(df_reset)
# Nombre Edad Ciudad Profesión Año_Nacimiento
# 0 Ana 25 Madrid Ingeniera 1998
# 1 Juan 30 Barcelona Médico 1993
# 2 María 22 Sevilla Profesora 2001
# 3 Pedro 40 Valencia Arquitecto 1983
# 4 Laura 28 Zaragoza Diseñadora 1995
# Estadísticas de columnas numéricas
print(df_reset.describe())
# Edad Año_Nacimiento
# count 5.000000 5.000000
# mean 29.000000 1994.000000
# std 6.782330 7.106335
# min 22.000000 1983.000000
# 25% 25.000000 1988.000000
# 50% 28.000000 1995.000000
# 75% 30.000000 1998.000000
# max 40.000000 2001.000000
# Estadísticas individuales
print(f"Media de edad: {df_reset['Edad'].mean()}")
print(f"Edad mínima: {df_reset['Edad'].min()}")
print(f"Edad máxima: {df_reset['Edad'].max()}")
Agrupación de datos
La función groupby()
permite agrupar datos según criterios específicos:
# Crear un DataFrame más grande para el ejemplo
datos_ventas = {
'Fecha': pd.date_range('2023-01-01', periods=10),
'Vendedor': ['Ana', 'Juan', 'María', 'Pedro', 'Ana', 'Juan', 'María', 'Pedro', 'Ana', 'Juan'],
'Producto': ['Laptop', 'Móvil', 'Tablet', 'Laptop', 'Móvil', 'Tablet', 'Laptop', 'Móvil', 'Tablet', 'Laptop'],
'Unidades': [5, 10, 8, 12, 6, 9, 7, 11, 4, 10],
'Precio': [800, 500, 300, 800, 550, 320, 780, 520, 310, 790]
}
df_ventas = pd.DataFrame(datos_ventas)
df_ventas['Total'] = df_ventas['Unidades'] * df_ventas['Precio']
print(df_ventas)
# Fecha Vendedor Producto Unidades Precio Total
# 0 2023-01-01 Ana Laptop 5 800 4000
# 1 2023-01-02 Juan Móvil 10 500 5000
# 2 2023-01-03 María Tablet 8 300 2400
# 3 2023-01-04 Pedro Laptop 12 800 9600
# 4 2023-01-05 Ana Móvil 6 550 3300
# 5 2023-01-06 Juan Tablet 9 320 2880
# 6 2023-01-07 María Laptop 7 780 5460
# 7 2023-01-08 Pedro Móvil 11 520 5720
# 8 2023-01-09 Ana Tablet 4 310 1240
# 9 2023-01-10 Juan Laptop 10 790 7900
# Agrupar por vendedor y calcular el total de ventas
ventas_por_vendedor = df_ventas.groupby('Vendedor')['Total'].sum()
print(ventas_por_vendedor)
# Vendedor
# Ana 8540
# Juan 15780
# María 7860
# Pedro 15320
# Name: Total, dtype: int64
# Agrupar por producto y calcular unidades vendidas
unidades_por_producto = df_ventas.groupby('Producto')['Unidades'].sum()
print(unidades_por_producto)
# Producto
# Laptop 34
# Móvil 27
# Tablet 21
# Name: Unidades, dtype: int64
# Múltiples estadísticas por grupo
resumen_por_vendedor = df_ventas.groupby('Vendedor').agg({
'Total': ['sum', 'mean'],
'Unidades': ['sum', 'mean', 'max']
})
print(resumen_por_vendedor)
# Total Unidades
# sum mean sum mean max
# Vendedor
# Ana 8540 2846.667 15 5.0 6
# Juan 15780 5260.000 29 9.7 10
# María 7860 3930.000 15 7.5 8
# Pedro 15320 7660.000 23 11.5 12
# Agrupar por múltiples columnas
resumen_detallado = df_ventas.groupby(['Vendedor', 'Producto'])['Total'].sum()
print(resumen_detallado)
# Vendedor Producto
# Ana Laptop 4000
# Móvil 3300
# Tablet 1240
# Juan Laptop 7900
# Móvil 5000
# Tablet 2880
# María Laptop 5460
# Tablet 2400
# Pedro Laptop 9600
# Móvil 5720
# Name: Total, dtype: int64
Fusión y combinación de datos
Pandas proporciona diferentes formas de combinar DataFrames:
Concatenación
# Dividir nuestro DataFrame en dos
df_parte1 = df_ventas.iloc[0:5]
df_parte2 = df_ventas.iloc[5:10]
# Concatenar verticalmente (unir filas)
df_concat_v = pd.concat([df_parte1, df_parte2])
print(df_concat_v) # Resultado igual a df_ventas original
# Concatenar horizontalmente (unir columnas)
df_a = df_ventas[['Fecha', 'Vendedor', 'Producto']]
df_b = df_ventas[['Unidades', 'Precio', 'Total']]
df_concat_h = pd.concat([df_a, df_b], axis=1)
print(df_concat_h) # Resultado igual a df_ventas original
Merge (Uniones tipo SQL)
# Crear DataFrames para el ejemplo
clientes = pd.DataFrame({
'ID': [1, 2, 3, 4, 5],
'Nombre': ['Ana', 'Juan', 'María', 'Pedro', 'Laura'],
'Ciudad': ['Madrid', 'Barcelona', 'Sevilla', 'Valencia', 'Zaragoza']
})
pedidos = pd.DataFrame({
'Pedido_ID': [101, 102, 103, 104, 105, 106],
'Cliente_ID': [1, 2, 3, 1, 4, 2],
'Producto': ['Laptop', 'Móvil', 'Tablet', 'Monitor', 'Impresora', 'Altavoces'],
'Monto': [800, 500, 300, 200, 150, 80]
})
# Inner join (solo registros que coinciden en ambos DataFrames)
df_inner = pd.merge(clientes, pedidos, left_on='ID', right_on='Cliente_ID')
print(df_inner)
# ID Nombre Ciudad Pedido_ID Cliente_ID Producto Monto
# 0 1 Ana Madrid 101 1 Laptop 800
# 1 1 Ana Madrid 104 1 Monitor 200
# 2 2 Juan Barcelona 102 2 Móvil 500
# 3 2 Juan Barcelona 106 2 Altavoces 80
# 4 3 María Sevilla 103 3 Tablet 300
# 5 4 Pedro Valencia 105 4 Impresora 150
# Left join (todos los registros del DataFrame izquierdo)
df_left = pd.merge(clientes, pedidos, left_on='ID', right_on='Cliente_ID', how='left')
print(df_left)
# ID Nombre Ciudad Pedido_ID Cliente_ID Producto Monto
# 0 1 Ana Madrid 101.0 1.0 Laptop 800.0
# 1 1 Ana Madrid 104.0 1.0 Monitor 200.0
# 2 2 Juan Barcelona 102.0 2.0 Móvil 500.0
# 3 2 Juan Barcelona 106.0 2.0 Altavoces 80.0
# 4 3 María Sevilla 103.0 3.0 Tablet 300.0
# 5 4 Pedro Valencia 105.0 4.0 Impresora 150.0
# 6 5 Laura Zaragoza NaN NaN NaN NaN
# Right join (todos los registros del DataFrame derecho)
df_right = pd.merge(clientes, pedidos, left_on='ID', right_on='Cliente_ID', how='right')
print(df_right) # En este caso, igual que inner join porque todos los pedidos tienen cliente
# Outer join (todos los registros de ambos DataFrames)
df_outer = pd.merge(clientes, pedidos, left_on='ID', right_on='Cliente_ID', how='outer')
print(df_outer)
# ID Nombre Ciudad Pedido_ID Cliente_ID Producto Monto
# 0 1 Ana Madrid 101.0 1.0 Laptop 800.0
# 1 1 Ana Madrid 104.0 1.0 Monitor 200.0
# 2 2 Juan Barcelona 102.0 2.0 Móvil 500.0
# 3 2 Juan Barcelona 106.0 2.0 Altavoces 80.0
# 4 3 María Sevilla 103.0 3.0 Tablet 300.0
# 5 4 Pedro Valencia 105.0 4.0 Impresora 150.0
# 6 5 Laura Zaragoza NaN NaN NaN NaN
Operaciones con series temporales
Pandas tiene excelente soporte para trabajar con datos de series temporales:
# Crear una Series con fechas como índice
fechas = pd.date_range('2023-01-01', periods=6)
valores = [100, 105, 110, 115, 120, 125]
serie_temporal = pd.Series(valores, index=fechas)
print(serie_temporal)
# 2023-01-01 100
# 2023-01-02 105
# 2023-01-03 110
# 2023-01-04 115
# 2023-01-05 120
# 2023-01-06 125
# Freq: D, dtype: int64
# Acceder por fecha
print(serie_temporal['2023-01-03']) # 110
# Rebanado de fechas
print(serie_temporal['2023-01-02':'2023-01-04'])
# 2023-01-02 105
# 2023-01-03 110
# 2023-01-04 115
# Freq: D, dtype: int64
# Remuestreo a frecuencia menor (agrupación temporal)
print(serie_temporal.resample('2D').mean())
# 2023-01-01 102.5
# 2023-01-03 112.5
# 2023-01-05 122.5
# Freq: 2D, dtype: float64
# Operaciones con desplazamiento temporal
print(serie_temporal.shift(1)) # Desplazar un día hacia adelante
# 2023-01-01 NaN
# 2023-01-02 100.0
# 2023-01-03 105.0
# 2023-01-04 110.0
# 2023-01-05 115.0
# 2023-01-06 120.0
# Freq: D, dtype: float64
# Cambio porcentual
print(serie_temporal.pct_change())
# 2023-01-01 NaN
# 2023-01-02 0.050000
# 2023-01-03 0.047619
# 2023-01-04 0.045455
# 2023-01-05 0.043478
# 2023-01-06 0.041667
# Freq: D, dtype: float64
Entrada y salida de datos
Pandas puede leer y escribir datos en varios formatos:
CSV
# Guardar DataFrame a CSV
df_ventas.to_csv('ventas.csv', index=False)
# Leer CSV
df_leido = pd.read_csv('ventas.csv')
print(df_leido.head())
Excel
# Requiere openpyxl o xlrd
# pip install openpyxl
# Guardar DataFrame a Excel
df_ventas.to_excel('ventas.xlsx', sheet_name='Datos', index=False)
# Leer Excel
df_excel = pd.read_excel('ventas.xlsx', sheet_name='Datos')
print(df_excel.head())
SQL
# Requiere SQLAlchemy
# pip install sqlalchemy
from sqlalchemy import create_engine
# Conexión a una base de datos SQLite
engine = create_engine('sqlite:///mi_base_datos.db')
# Guardar DataFrame a una tabla SQL
df_ventas.to_sql('ventas', engine, if_exists='replace', index=False)
# Leer tabla SQL
df_sql = pd.read_sql('SELECT * FROM ventas', engine)
print(df_sql.head())
JSON
# Guardar DataFrame a JSON
df_ventas.to_json('ventas.json')
# Leer JSON
df_json = pd.read_json('ventas.json')
print(df_json.head())
Visualización de datos con Pandas
Pandas integra Matplotlib para crear visualizaciones rápidamente:
# Importar matplotlib (requerido para mostrar gráficos)
import matplotlib.pyplot as plt
# Gráfico de barras
ventas_por_vendedor.plot(kind='bar')
plt.title('Ventas totales por vendedor')
plt.ylabel('Ventas (€)')
plt.tight_layout()
plt.show()
# Gráfico de líneas para serie temporal
serie_temporal.plot()
plt.title('Evolución temporal')
plt.ylabel('Valor')
plt.tight_layout()
plt.show()
# Histograma
df_ventas['Unidades'].plot(kind='hist', bins=5)
plt.title('Distribución de unidades vendidas')
plt.xlabel('Unidades')
plt.tight_layout()
plt.show()
# Gráfico de dispersión
df_ventas.plot.scatter(x='Precio', y='Unidades')
plt.title('Relación entre precio y unidades vendidas')
plt.tight_layout()
plt.show()
Caso práctico: Análisis de ventas
Veamos un ejemplo completo de análisis con Pandas:
# Supongamos que tenemos nuestro DataFrame de ventas
print(df_ventas.head())
# 1. Análisis exploratorio
print("Estadísticas descriptivas:")
print(df_ventas.describe())
# 2. Ventas por día de la semana
df_ventas['DiaSemana'] = df_ventas['Fecha'].dt.day_name()
ventas_dia = df_ventas.groupby('DiaSemana')['Total'].sum()
print("\nVentas por día de la semana:")
print(ventas_dia)
# 3. Producto más vendido por vendedor
top_producto = df_ventas.groupby(['Vendedor', 'Producto'])['Unidades'].sum().reset_index()
idx = top_producto.groupby('Vendedor')['Unidades'].idxmax()
mejor_producto = top_producto.loc[idx]
print("\nProducto más vendido por cada vendedor:")
print(mejor_producto)
# 4. Evolución diaria de ventas
ventas_diarias = df_ventas.groupby('Fecha')['Total'].sum()
print("\nEvolución diaria de ventas:")
print(ventas_diarias)
# 5. Análisis de correlación
print("\nCorrelación entre variables:")
print(df_ventas[['Unidades', 'Precio', 'Total']].corr())
# 6. Visualización de resultados
plt.figure(figsize=(12, 10))
# Gráfico 1: Ventas por vendedor
plt.subplot(2, 2, 1)
ventas_por_vendedor.plot(kind='bar', ax=plt.gca())
plt.title('Ventas por vendedor')
plt.ylabel('Ventas (€)')
# Gráfico 2: Unidades por producto
plt.subplot(2, 2, 2)
unidades_por_producto.plot(kind='pie', autopct='%1.1f%%', ax=plt.gca())
plt.title('Distribución de unidades por producto')
# Gráfico 3: Evolución diaria de ventas
plt.subplot(2, 2, 3)
ventas_diarias.plot(ax=plt.gca())
plt.title('Evolución diaria de ventas')
plt.ylabel('Ventas (€)')
# Gráfico 4: Relación precio-unidades
plt.subplot(2, 2, 4)
df_ventas.plot.scatter(x='Precio', y='Unidades', ax=plt.gca())
plt.title('Relación entre precio y unidades')
plt.tight_layout()
plt.show()
Resumen
Pandas es una herramienta fundamental para el análisis de datos en Python. Proporciona estructuras de datos versátiles como Series y DataFrames, que facilitan la manipulación, limpieza y análisis de datos. Hemos explorado operaciones básicas como selección, filtrado, agrupación, fusión de datos y trabajo con series temporales. También hemos visto cómo importar y exportar datos en diferentes formatos y crear visualizaciones sencillas. Pandas es extremadamente útil tanto para análisis exploratorios rápidos como para preparar datos para análisis más complejos. En los siguientes temas, exploraremos herramientas más específicas para visualización de datos, como Matplotlib, que complementan perfectamente a Pandas.