Leer un CSV y comprobar qué llegó
Cómo leer un archivo con read_csv e inspeccionarlo de inmediato con shape, head, info y describe: porque un archivo mal leído da respuestas incorrectas sin generar jamás un error.
¿Cómo quieres aprender?
El problema que vamos a resolver
Hasta ahora, cada valor de la tabla se ha escrito a mano en el código. Para tres filas, eso funciona.
Los datos reales no viven en el código. Viven en un archivo: enviado por correo electrónico por alguien, exportado desde un sistema o guardado a partir de una hoja de cálculo. Y el archivo tiene doce mil filas, no doce.
Ese archivo suele verse así: texto plano, los nombres de las columnas en la primera línea y luego una fila por línea, separadas por comas:
product,quantity,price
pen,12,15.0
notebook,5,60.0Esto es un CSV: comma-separated values (valores separados por comas). Convertirlo en una tabla requiere una sola línea de pandas, y es la línea más utilizada de toda la biblioteca.
Pero hay un hábito que debes adquirir inmediatamente después de esa línea, y es el verdadero tema de este capítulo: una vez leído un archivo, míralo. Cuántas filas llegaron, si los nombres de las columnas son los que esperabas, si las columnas numéricas realmente entraron como números. Si te saltas esos treinta segundos, el error saldrá a la luz mucho después, cuando una respuesta esté mal y nada haya generado un error.
Al terminar este capítulo podrás
- Leer un archivo con
pd.read_csv()y resolver el problema de rutas que suele surgir - Comprobar un archivo rápidamente con
head(),tail(),shapeycolumns - Leer
info()para ver el recuento de filas, celdas vacías y el tipo de cada columna a la vez - Resumir las columnas numéricas con
describe() - Reconocer y solucionar un
FileNotFoundErrory un separador incorrecto
Requisitos previos: Series y DataFrame — las dos estructuras fundamentales de pandas.
Crea el archivo primero
En la carpeta de tu proyecto, crea un archivo llamado sales.csv con exactamente estas seis líneas:
product,quantity,price
pen,12,15.0
notebook,5,60.0
bag,2,850.0
bottle,7,120.0
eraser,30,8.0La primera línea no son datos, son los nombres de las columnas: el encabezado (header). Las otras cinco líneas son cinco filas.
Leerlo en una sola línea
import pandas as pd
sales = pd.read_csv("sales.csv")
print(sales)product quantity price
0 pen 12 15.0
1 notebook 5 60.0
2 bag 2 850.0
3 bottle 7 120.0
4 eraser 30 8.0Esa única línea hizo tres cosas, y las tres de forma silenciosa:
Primero, tomó la primera línea como encabezado, de modo que product, quantity y price se convirtieron en nombres de columnas en lugar de una fila.
Segundo, construyó un índice, los números del 0 al 4 a la izquierda. Eso no estaba en el archivo.
Tercero, y esto es lo verdaderamente importante, dedujo el tipo de cada columna. Todo en el archivo es texto: 12 son en realidad dos caracteres. Pandas examinó cada columna y decidió si eran números o texto.
Esta deducción suele ser acertada. Pero cuando se equivoca, nada arroja un error; y esa es precisamente la razón por la que debes mirar.
Las cuatro cosas que debes comprobar después de leer un archivo
shape — cuánto se ha cargado
print(sales.shape)(5, 3)Cinco filas, tres columnas. El archivo tenía seis líneas y este tiene cinco filas, porque el encabezado no es una fila. Si el número está muy por debajo de lo esperado, o hay exactamente una fila de más, esa es la primera señal de que algo se leyó mal.
head() y tail() — el principio y el final
print(sales.head(3))product quantity price
0 pen 12 15.0
1 notebook 5 60.0
2 bag 2 850.0Imprimir las doce mil filas de un archivo real llena la terminal y no te dice nada. head() muestra las primeras filas: cinco si no indicas un número. tail() hace lo mismo al final, y mirar el final es útil por otra razón: los archivos exportados a menudo incluyen una línea en blanco suelta o una fila de totales al final.
info() — todo de un vistazo
sales.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 product 5 non-null object
1 quantity 5 non-null int64
2 price 5 non-null float64
dtypes: float64(1), int64(1), object(1)
memory usage: 252.0+ bytesFíjate en que se escribe sales.info() y no print(sales.info()): este método imprime por sí mismo y no devuelve nada, por lo que envolverlo en print añade un None suelto al final.
Esto es lo más útil que puedes ejecutar después de leer un archivo, porque reúne dos datos importantes:
Non-Null Count: cuántas celdas de cada columna están realmente llenas. Aquí las tres dicen 5 non-null, por lo que ninguna está vacía. Un 4 non-null en cualquier columna significa que una celda de esa columna está en blanco, y eso cambiará tus cálculos aritméticos.
Dtype: el tipo determinado por la deducción. quantity entró como int64, price como float64 y product como object. Eso es lo que queríamos.
(La cifra de memory usage en la última línea puede diferir en tu máquina y no tiene importancia).
describe() — un resumen de las columnas numéricas
print(sales.describe())quantity price
count 5.00000 5.000000
mean 11.20000 210.600000
std 11.12205 360.217712
min 2.00000 8.000000
25% 5.00000 15.000000
50% 7.00000 60.000000
75% 12.00000 120.000000
max 30.00000 850.000000Selecciona las columnas numéricas y realiza ocho cálculos en cada una. product no aparece porque es texto.
Hay algo aquí que debería llamar tu atención: la media (mean) de price es 210.6, mientras que el 50% —la mediana— es de solo 60. Una diferencia tan amplia significa que un valor se sitúa muy por encima del resto, y max lo identifica: 850. Así es como se lee describe(): cuando la media y la mediana se distancian, mira allí.
Un ejemplo completo
report.py:
import pandas as pd
sales = pd.read_csv("sales.csv")
print("Rows, columns:", sales.shape)
print()
print(sales.head(3))
print()
print("Columns :", list(sales.columns))
print("Total qty :", sales["quantity"].sum())
print("Avg price :", round(sales["price"].mean(), 2))Rows, columns: (5, 3)
product quantity price
0 pen 12 15.0
1 notebook 5 60.0
2 bag 2 850.0
Columns : ['product', 'quantity', 'price']
Total qty : 56
Avg price : 210.6Un programa pequeño, pero vale la pena fijarse en su estructura: leer, luego comprobar, después calcular. shape y head() no son cálculos, son preguntas: ¿he leído el archivo correcto? ¿Hay tantas filas como debería haber?
Y hay una razón para imprimir list(sales.columns). Como lista, cada nombre aparece entre comillas, por lo que un nombre como 'quantity ' con un espacio al final resulta visible de inmediato. Si se imprime de cualquier otra forma, ese espacio permanece invisible y reaparece más tarde como un KeyError.
Cuando algo falla
FileNotFoundError: [Errno 2] No such file or directory: 'sales.csv' Python busca en la carpeta actual y no lo encuentra allí. Es el mismo problema que en el capítulo dos del curso de Python: la terminal está en un lugar y el archivo en otro. Ejecuta pwd para ver dónde estás, dir para ver si el archivo está ahí y luego cd. En Windows, el nombre real podría ser sales.csv.txt; activa las extensiones de nombre de archivo en el Explorador.
Todo el archivo se cargó como una sola columna El separador no es una coma. Los archivos guardados en gran parte de Europa usan punto y coma, porque allí la coma es el separador decimal. Escribe pd.read_csv("sales.csv", sep=";"). Para archivos separados por tabulaciones, usa sep="\t".
Una columna numérica entró como object Se ha colado texto en alguna parte de la columna: un N/A, un -, una celda vacía o una coma de miles (1,200). Ejecuta df["col"].unique() para ver qué hay realmente allí; el valor anómalo suele destacar. La solución es pd.to_numeric(df["col"], errors="coerce"), que convierte cualquier valor no numérico en un valor faltante, algo que se trata en detalle en el capítulo sobre datos faltantes.
UnicodeDecodeError El archivo no está guardado en UTF-8, algo que ocurre con frecuencia con archivos exportados de hojas de cálculo. Prueba con pd.read_csv("sales.csv", encoding="utf-8-sig") y, si eso no funciona, con encoding="latin-1".
La primera fila de datos se convirtió en los nombres de las columnas, aunque el archivo no tenía encabezado Escribe pd.read_csv("sales.csv", header=None) y las columnas pasarán a ser 0, 1, 2. Para darles nombre, añade names=["product", "quantity", "price"].
Aparece un None suelto impreso después de sales.info() Se escribió como print(sales.info()). info() imprime por sí mismo y no devuelve nada, por lo que print está imprimiendo el None que devolvió. Escribe simplemente sales.info().
Paso 4 de 6 — Predice
Comprueba lo que has entendido
El archivo tiene seis líneas. ¿Qué indica shape?
from io import StringIO
import pandas as pd
# Stands in for sales.csv, so this snippet runs on its own.
RAW = """product,quantity,price
pen,12,15.0
notebook,5,60.0
bag,2,850.0
bottle,7,120.0
eraser,30,8.0
"""
sales = pd.read_csv(StringIO(RAW))
print(sales.shape)- A(5, 3)
- B(5, 4)
- C(3, 5)
- D(6, 3)
¿Qué te indica la columna Non-Null Count de info()?
- ACuántas celdas de cada columna están realmente llenas: un número inferior al total de filas significa que hay celdas vacías
- BCuántas celdas de cada columna están vacías
- CCuánto espacio ocupa cada columna
- DCuántos valores distintos tiene cada columna
El archivo está separado por punto y coma, pero no se especificó sep. ¿Qué se imprime?
from io import StringIO
import pandas as pd
# Stands in for sales.csv, so this snippet runs on its own.
RAW = """product;quantity
pen;12
notebook;5
"""
df = pd.read_csv(StringIO(RAW))
print(df.shape)
print(list(df.columns))- A(3, 1) ['product;quantity']
- B(2, 1) ['product;quantity']
- C(2, 2) ['product', 'quantity']
- DUn `ParserError`
Para responder necesitas una cuenta
Inicia sesión para comprobar tus respuestas
Las preguntas están arriba, y resolverlas mentalmente es lo que de verdad importa. Inicia sesión para ver las respuestas, las explicaciones y las pistas de tres niveles.
Tu turno
Crea un archivo llamado students.csv que contenga al menos ocho personas, en tres columnas: un nombre, una edad y una calificación.
Luego escribe report.py, que:
- Lea el archivo
- Imprima
shapeylist(columns) - Imprima
head(3)ytail(2) - Ejecute
info()e indique si los tipos de las tres columnas son los que esperabas - Imprima
describe(), y por separado la media y el valor máximo de la columna de calificaciones
Luego rómpelo a propósito, tres veces, observando qué sucede en cada caso:
- Pon
N/Aen una celda de la columna de calificaciones. ¿Qué dice ahoraDtypeeninfo()? ¿Qué ocurrió con la media? - Reemplaza cada coma del archivo por un punto y coma. ¿Qué indica
shapeahora y por qué? - Elimina la primera línea, el encabezado. ¿Cuántas filas se cargaron y cuáles son los nombres de las columnas ahora?
Las tres situaciones ocurren habitualmente en el trabajo real, y cada una tiene un síntoma claro. Provocarlas deliberadamente hoy te permitirá reconocerlas a simple vista la próxima vez.
Paso 6 de 6
Reto — el quiz del capítulo
Diez preguntas de fácil a difícil. Las últimas son difíciles a propósito.
Inicia sesión para hacer el quiz