Trabajar con CSV y Excel en Python: pandas y openpyxl
Python ofrece varias bibliotecas para manejar hojas de cálculo. pandas es la opción potente para análisis y transformación de datos; openpyxl permite leer/escribir archivos .xlsx con formato, estilos y fórmulas.
1. Leer y escribir CSV con el módulo csv
import csv
from pathlib import Path
# Escribir CSV
datos = [
{"nombre": "Ana", "edad": 28, "ciudad": "Madrid"},
{"nombre": "Carlos","edad": 34, "ciudad": "Barcelona"},
{"nombre": "Lucía", "edad": 22, "ciudad": "Sevilla"},
]
with open("personas.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["nombre", "edad", "ciudad"])
writer.writeheader()
writer.writerows(datos)
# Leer CSV
with open("personas.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for fila in reader:
print(f"{fila['nombre']} ({fila['edad']}) — {fila['ciudad']}")
2. pandas: leer CSV y Excel
pip install pandas openpyxl xlrd
import pandas as pd
# Leer CSV
df = pd.read_csv("personas.csv")
print(df.head())
print(df.dtypes)
# Opciones útiles
df = pd.read_csv(
"datos.csv",
sep=";", # Separador alternativo
encoding="latin-1", # Codificación
decimal=",", # Coma decimal (Europa)
parse_dates=["fecha"], # Columna fecha → datetime
index_col=0, # Primera columna como índice
)
# Leer Excel
df_excel = pd.read_excel("informe.xlsx", sheet_name="Ventas")
print(df_excel.shape) # (filas, columnas)
3. Exploración y limpieza de datos
import pandas as pd
df = pd.DataFrame({
"nombre": ["Ana", "Carlos", "Lucía", "Ana", None],
"edad": [28, 34, 22, 28, 45],
"ciudad": ["Madrid", "Barcelona", "Sevilla", "Madrid", "Valencia"],
"salario": [35000, 42000, None, 35000, 55000],
})
# Información general
print(df.info())
print(df.describe())
# Valores nulos
print(df.isnull().sum())
# Eliminar filas con nulos
df_limpio = df.dropna()
# Rellenar nulos
df["salario"] = df["salario"].fillna(df["salario"].mean())
df["nombre"] = df["nombre"].fillna("Desconocido")
# Eliminar duplicados
df_sin_dup = df.drop_duplicates()
df_sin_dup_cols = df.drop_duplicates(subset=["nombre", "ciudad"])
# Convertir tipos
df["edad"] = df["edad"].astype(int)
4. Filtrar, ordenar y agrupar
import pandas as pd
df = pd.read_csv("personas.csv")
# Filtrar filas
mayores = df[df["edad"] > 25]
madrid = df[df["ciudad"] == "Madrid"]
filtro = df[(df["edad"] > 25) & (df["ciudad"] != "Barcelona")]
# query() — más legible
resultado = df.query("edad > 25 and ciudad != 'Barcelona'")
# Ordenar
ordenado = df.sort_values("edad", ascending=False)
multi = df.sort_values(["ciudad", "edad"], ascending=[True, False])
# Agrupar y agregar
por_ciudad = df.groupby("ciudad")["salario"].agg(["mean", "min", "max", "count"])
print(por_ciudad)
# Pivot table
tabla = df.pivot_table(
values="salario",
index="ciudad",
columns="departamento",
aggfunc="mean",
fill_value=0,
)
5. Transformar datos
import pandas as pd
df = pd.DataFrame({
"nombre": ["Ana García", "Carlos López"],
"salario": [35000, 42000],
"fecha": ["2025-01-15", "2025-03-20"],
})
# Aplicar función a columna
df["salario_mensual"] = df["salario"] / 12
df["nombre_upper"] = df["nombre"].str.upper()
df["apellido"] = df["nombre"].str.split().str[-1]
# apply: función personalizada
def categoria_salario(s):
if s < 30000: return "bajo"
if s < 50000: return "medio"
return "alto"
df["categoria"] = df["salario"].apply(categoria_salario)
# Columnas de fecha
df["fecha"] = pd.to_datetime(df["fecha"])
df["mes"] = df["fecha"].dt.month
df["anio"] = df["fecha"].dt.year
df["dia_semana"] = df["fecha"].dt.day_name()
6. Exportar con pandas
import pandas as pd
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
# CSV
df.to_csv("salida.csv", index=False, encoding="utf-8")
# Excel (una hoja)
df.to_excel("salida.xlsx", index=False, sheet_name="Datos")
# Excel (múltiples hojas)
with pd.ExcelWriter("multi_hoja.xlsx", engine="openpyxl") as writer:
df.to_excel(writer, sheet_name="Hoja1", index=False)
df.to_excel(writer, sheet_name="Hoja2", index=False)
# JSON
df.to_json("salida.json", orient="records", force_ascii=False, indent=2)
7. openpyxl: formato, estilos y fórmulas
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter
wb = Workbook()
ws = wb.active
ws.title = "Ventas"
# Cabecera con estilo
cabeceras = ["Producto", "Unidades", "Precio", "Total"]
for col, cabecera in enumerate(cabeceras, 1):
celda = ws.cell(row=1, column=col, value=cabecera)
celda.font = Font(bold=True, color="FFFFFF")
celda.fill = PatternFill("solid", fgColor="2E7D32")
celda.alignment = Alignment(horizontal="center")
# Datos con fórmula
datos = [("Teclado", 50, 25.99), ("Ratón", 80, 12.50), ("Monitor", 30, 199.99)]
for fila, (prod, uni, precio) in enumerate(datos, 2):
ws.cell(row=fila, column=1, value=prod)
ws.cell(row=fila, column=2, value=uni)
ws.cell(row=fila, column=3, value=precio)
# Fórmula Excel
ws.cell(row=fila, column=4, value=f"=B{fila}*C{fila}")
# Ajustar ancho de columna
for col in range(1, 5):
ws.column_dimensions[get_column_letter(col)].width = 15
wb.save("ventas.xlsx")
print("Excel guardado.")
8. openpyxl: leer y modificar archivos existentes
from openpyxl import load_workbook
wb = load_workbook("ventas.xlsx")
ws = wb.active
# Leer datos
for fila in ws.iter_rows(min_row=2, values_only=True):
producto, unidades, precio, total = fila
print(f"{producto}: {unidades} × {precio:.2f} = {total}")
# Modificar una celda
ws["D5"] = "=B5*C5*1.21" # IVA incluido
# Añadir una hoja
ws2 = wb.create_sheet("Resumen")
ws2["A1"] = "Total ventas"
ws2["B1"] = f"=SUM(Ventas!D2:D{ws.max_row})"
wb.save("ventas_modificado.xlsx")
9. Convertir CSV a Excel con formato
import csv
import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import Font, PatternFill
# Paso 1: leer CSV y convertir a xlsx con pandas
df = pd.read_csv("datos.csv")
df.to_excel("datos_formateados.xlsx", index=False)
# Paso 2: abrir con openpyxl y aplicar estilos
wb = load_workbook("datos_formateados.xlsx")
ws = wb.active
# Estilo de cabecera
for celda in ws[1]:
celda.font = Font(bold=True, color="FFFFFF")
celda.fill = PatternFill("solid", fgColor="1565C0")
# Congelar fila de cabecera
ws.freeze_panes = "A2"
# Filtros automáticos
ws.auto_filter.ref = ws.dimensions
wb.save("datos_formateados.xlsx")
print("CSV convertido a Excel con formato.")
10. Trabajar con archivos grandes: chunks
import pandas as pd
# Leer en chunks para no cargar todo en RAM
total_filas = 0
suma_precio = 0
for chunk in pd.read_csv("archivo_grande.csv", chunksize=10_000):
# Filtrar y procesar por lotes
chunk_filtrado = chunk[chunk["precio"] > 0]
total_filas += len(chunk_filtrado)
suma_precio += chunk_filtrado["precio"].sum()
print(f"Filas válidas: {total_filas}")
print(f"Precio medio : {suma_precio / total_filas:.2f}")
Resumen: ¿qué herramienta usar?
| Tarea | Herramienta |
|---|---|
| Leer/escribir CSV simple | csv (stdlib) |
| Análisis y transformación | pandas |
| Leer Excel sin formato | pandas + openpyxl |
| Escribir Excel con estilos | openpyxl |
Leer .xls antiguo (Excel 97-2003) |
xlrd |
| Archivos muy grandes | pandas con chunksize |
| Operaciones SQL sobre DataFrames | pandas + df.query() |
Conversiones relacionadas
Conversiones de documento que siguen este tema: