CSV: Guía Técnica Completa de Valores Separados por Comas
CSV (Comma-Separated Values) es el formato más antiguo y universal para el intercambio de datos tabulares. Definido informalmente durante décadas, fue parcialmente formalizado en RFC 4180 (2005) — aunque las implementaciones siguen divergiendo significativamente. La fortaleza de CSV es su simplicidad radical: cualquier hoja de cálculo, base de datos, lenguaje de programación y herramienta de línea de comandos puede leerlo y escribirlo. Su debilidad es la misma: sin codificación estándar, sin tipos, sin esquema y sin forma canónica de manejar casos límite.
Especificación RFC 4180
RFC 4180 define las reglas que la mayoría de productores y consumidores de CSV siguen:
- Cada registro ocupa exactamente una línea, terminada con CRLF (
\r\n). - El último registro puede omitir opcionalmente el CRLF final.
- Una fila de cabecera opcional contiene nombres de columnas y debe tener el mismo número de campos que los registros de datos.
- Los campos pueden o no estar encerrados entre comillas dobles.
- Los campos que contienen comillas dobles, comas o CRLF deben encerrarse entre comillas dobles.
- Una comilla doble dentro de un campo entre comillas se representa con dos comillas dobles consecutivas (
""). - El tipo MIME es
text/csv; la extensión de archivo es.csv.
La Regla de Escape con Comillas Dobles
La regla más crítica: para incrustar una comilla doble literal dentro de un campo entre comillas, debes duplicarla:
"Dijo, ""¡Hola, mundo!"""
Se parsea como: Dijo, "¡Hola, mundo!"
Los campos con saltos de línea incrustados son legales en RFC 4180 — el campo se envuelve entre comillas.
Lo que RFC 4180 No Define
- Codificación de caracteres: RFC 4180 especifica US-ASCII. Los CSV del mundo real usan UTF-8 (preferido), Windows-1252 o Latin-1.
- BOM: Algunos CSV generados por Excel incluyen un BOM UTF-8 (
\xEF\xBB\xBF). Usaencoding='utf-8-sig'en Python para manejarlo. - Delimitador: El nombre dice "coma" pero TSV (tabulador), SSV (punto y coma en locales europeos) y variantes delimitadas por pipe son muy comunes.
- Formato de fecha/número: Sin estándar. Usa ISO 8601 (
2025-04-26) para fechas. - NULL vs vacío: Un campo vacío
,,es ambiguo — podría significar NULL o string vacío.
Módulo csv de Python
import csv
from pathlib import Path
# --- Lectura ---
# Especifica siempre la codificación; utf-8-sig maneja el BOM de Excel
with open('datos.csv', encoding='utf-8-sig', newline='') as f:
lector = csv.DictReader(f)
for fila in lector:
print(fila['nombre'], fila['puntuacion'])
# --- Escritura ---
campos = ['id', 'nombre', 'puntuacion', 'activo']
filas = [
{'id': 1, 'nombre': 'Alicia', 'puntuacion': 98.5, 'activo': True},
{'id': 2, 'nombre': 'Bob, Jr.', 'puntuacion': 87.0, 'activo': False},
{'id': 3, 'nombre': 'Carol "CC" Smith', 'puntuacion': 95.5, 'activo': True},
]
with open('salida.csv', 'w', encoding='utf-8', newline='') as f:
escritor = csv.DictWriter(f, fieldnames=campos)
escritor.writeheader()
escritor.writerows(filas)
# salida.csv:
# id,nombre,puntuacion,activo
# 1,Alicia,98.5,True
# 2,"Bob, Jr.",87.0,False
# 3,"Carol ""CC"" Smith",95.5,True
# --- Dialecto con punto y coma (CSVs europeos de Excel) ---
with open('europeo.csv', encoding='windows-1252', newline='') as f:
lector = csv.DictReader(f, delimiter=';')
for fila in lector:
print(fila)
Pandas para Archivos CSV Grandes
import pandas as pd
# Leer con inferencia de tipos
df = pd.read_csv(
'grande.csv',
encoding='utf-8',
dtype={'id': 'int64', 'puntuacion': 'float64'},
parse_dates=['creado_en'],
na_values=['', 'NULL', 'N/A'],
low_memory=False,
)
print(df.dtypes)
print(df.head())
print(df.describe())
# Filtrar y exportar
resultado = df[df['puntuacion'] > 90][['id', 'nombre', 'puntuacion']]
resultado.to_csv('altas_puntuaciones.csv', index=False, encoding='utf-8')
# Procesar en trozos (streaming de archivos grandes)
for trozo in pd.read_csv('enorme.csv', chunksize=10_000):
procesar(trozo)
# Formato europeo: punto y coma + coma decimal
df_eu = pd.read_csv('datos_eu.csv', sep=';', decimal=',')
Procesamiento por Línea de Comandos con csvkit
# Estadísticas de columnas
csvstat datos.csv
# Seleccionar columnas específicas
csvcut -c nombre,puntuacion datos.csv
# Filtrar filas
csvgrep -c puntuacion -m 98 datos.csv
csvgrep -c nombre -r "^A" datos.csv
# Unir dos archivos CSV por columna común
csvjoin -c id usuarios.csv puntuaciones.csv
# Ordenar
csvsort -c puntuacion -r datos.csv
# Convertir a JSON
csvjson datos.csv
# Consultas SQL contra CSV
csvsql --query "SELECT nombre, AVG(puntuacion) FROM datos GROUP BY nombre" datos.csv
Casos Límite Comunes y Trampas
El Problema de los Saltos de Línea
RFC 4180 exige terminaciones de línea CRLF (\r\n) pero los archivos CSV de Unix usan LF (\n). El módulo csv de Python maneja esto con newline='' en open(). Olvidar newline='' causa saltos de línea dobles en Windows.
El Requisito de BOM UTF-8 de Excel
Excel (versiones anteriores a 365) abre archivos CSV usando la codificación del locale del sistema. Los caracteres no-ASCII se verán corruptos a menos que el archivo comience con un BOM UTF-8. Escribe con encoding='utf-8-sig' para incluir el BOM.
Ambigüedad de Numéricos vs Strings
CSV no tiene tipos. Números de teléfono, códigos postales e IDs de producto almacenados como dígitos perderán sus ceros iniciales cuando los analicen herramientas que auto-detectan números. Siempre pon entre comillas los strings que parecen números o especifica los tipos de columna explícitamente en tu parser.
CSV vs Otros Formatos Tabulares
| Formato | Tipos | Esquema | Binario | Streaming | Compresión | Mejor para |
|---|---|---|---|---|---|---|
| CSV | No | No | No | Sí | Externa | Intercambio universal |
| TSV | No | No | No | Sí | Externa | Datos delimitados por tabulador |
| Excel (.xlsx) | Sí | No | Sí (ZIP) | No | Interna | Usuarios de negocio |
| Parquet | Sí | Sí | Sí | Sí | Interna (Snappy) | Analítica / data lakes |
| Arrow / Feather | Sí | Sí | Sí | Sí | Externa | Columnar en memoria |
| SQLite | Sí | Sí | Sí | Sí | No | Relacional embebido |
| JSON Lines | Parcial | No | No | Sí | Externa | Datos semi-estructurados |
Conversiones relacionadas
Conversiones de documento que siguen este tema: