La idea
Por los Fundamentos sabes que un DataFrame es una tabla de columnas con tipo. Este capítulo trata del hábito que lo acompaña: antes de calcular nada, mira. Unas pocas llamadas de una línea te dicen qué tamaño tiene la tabla, qué guarda cada columna, qué valores aparecen y con qué frecuencia. Saltárselas es como se calcula un total sobre la columna equivocada, o sobre una tabla con filas duplicadas, y luego se manda a un VP.
Figura 1
Un corchete da una Series, dos corchetes dan un DataFrame
| order_id | status | channel | shipping_fee |
|---|---|---|---|
| 1001 | completed | web | 0.00 |
| 1002 | completed | web | 0.00 |
| 1003 | completed | marketplace | 4.99 |
| 1006 | cancelled | marketplace | 4.99 |
| status |
|---|
| completed |
| completed |
| completed |
| cancelled |
| order_id | status |
|---|---|
| 1001 | completed |
| 1002 | completed |
| 1003 | completed |
| 1006 | cancelled |
- Partimos de
orders, un DataFrame con cuatro columnas. Casi nunca necesitas todas para una pregunta. orders['status'], un nombre entre corchetes simples, devuelve una Series: una columna de valores, con las etiquetas de fila pegadas. Tiene métodos para valores, comovalue_counts().orders[['order_id', 'status']], una lista dentro de los corchetes, devuelve un DataFrame con solo esas columnas, que sigue siendo una tabla. Los corchetes interiores son una lista de Python con nombres.
Lo primero es tener claro qué tienes en las manos. Un DataFrame es la tabla entera. Una Series es una columna de ella. Corchetes simples con un nombre dan una Series; corchetes dobles con una lista dan un DataFrame. Se imprimen casi igual, pero tienen métodos distintos, y confundirlos es el mensaje de error más común del capítulo.
Por qué existe
Las tablas reales nunca están tan limpias como te dijeron. Una columna documentada como "channel" tiene un valor que nadie mencionó. Una "fecha" está guardada como texto. Una clave que creías única se repite. Estos problemas no cuestan nada al principio y mucho cuando el informe ya salió. Las llamadas del primer vistazo tardan segundos, y su valor es que le haces las mismas preguntas a cada tabla nueva, en el mismo orden, sin tener que pensarlo.
Cómo funciona por dentro
El tamaño y los tipos
orders.shape da (12000, 7): primero filas, luego columnas. len(orders) da 12.000, el número de filas. orders.info() lista cada columna con su dtype y su cuenta de valores no vacíos, así que de un vistazo sabes qué columnas son números, cuáles son texto y cuáles tienen huecos. orders.head() muestra las primeras cinco filas, para que leas unos valores reales junto a los nombres de columna.
Contar los valores
Para una columna de categorías, value_counts() es la primera llamada. Devuelve una Series nueva: los valores distintos como índice y las cuentas como valores, de mayor a menor.
Figura 2
orders['status'].value_counts(): cómo terminaron los 12.000 pedidos
value_counts()cuenta cuántas veces aparece cada valor distinto, de mayor a menor. De 12.000 pedidos, 10.849 soncompleted: unos 9 de cada 10.- El resto es una cola corta. 726 cancelados y 304 reembolsados son los dos que investigarías; 121 siguen pendientes.
- Cuatro valores, cuatro barras, y las cuentas suman 12.000. Un quinto valor, un error como
Completed, aparecería aquí como su propia barra. Para eso sirve un primer vistazo.
Con normalize=True da fracciones en vez de cuentas, que es como se dice "el 90% de los pedidos se completó". Para una columna numérica, describe() da la cuenta, la media, la desviación estándar, el mínimo, los cuartiles y el máximo en una tabla. Léela como prueba de cordura: un precio mínimo de 0, o un máximo 100 veces la mediana, merece una mirada antes de confiar en cualquier promedio.
Contar filas frente a contar cosas
Tres llamadas se parecen y responden preguntas distintas. len(df) es el número de filas. series.count() es el número de filas con valor, así que se salta las vacías. series.nunique() es el número de valores diferentes.
Figura 3
count() y nunique() responden preguntas distintas
| order_id | customer_id |
|---|---|
| 1001 | 125 |
| 1002 | 156 |
| 1003 | 22 |
| 1004 | 48 |
| 1005 | 82 |
| 1006 | 157 |
| 1007 | 21 |
| 1008 | 157 |
| 1009 | 38 |
| 1010 | 111 |
| call | result |
|---|---|
| len(orders) | 10 |
| customer_id.count() | 10 |
| customer_id.nunique() | 9 |
- Diez pedidos. Cada uno tiene un
customer_id, pero los clientes pueden pedir más de una vez. count()cuenta los valores que no faltan. Los diez pedidos tienen cliente, así que son 10, igual quelen.- El cliente 157 hizo los pedidos 1006 y 1008.
nunique()cuenta valores distintos, así que el 157 cuenta una vez, y la respuesta es 9 clientes.
La segunda y la tercera son donde se esconden las respuestas equivocadas. "¿Cuántos clientes pidieron?" es nunique() sobre customer_id; el número de filas contaría cada compra repetida. "¿A cuántos pedidos les falta cupón?" es isna().sum() sobre coupon_code, y count() es su opuesto. unique() da los valores distintos en sí, no solo cuántos, que es la forma más rápida de detectar web y Web en la misma columna.
Cargar un archivo
pd.read_csv lee un archivo en un DataFrame y adivina el dtype de cada columna según lo que ve. Las fechas llegan como texto salvo que digas parse_dates=['order_date']. Una columna numérica con un "n/a" suelto llega como texto. Por eso, después de cargar, dtypes es la primera comprobación, antes de cualquier aritmética. NumPy, sobre el que se construye pandas, aporta los arreglos bajo las columnas, por eso np.mean, cumsum y la aritmética elemento a elemento funcionan directamente sobre ellas.
Una rutina que puedes repetir
Ejecuta la misma rutina corta en cada tabla nueva. Primero shape y head(): ¿cuánto hay y cómo es una fila? Luego info(): ¿los tipos son correctos y dónde están los huecos? Después value_counts() en cada columna de categorías y describe() en las numéricas: ¿los valores y los rangos tienen sentido? Por último, nunique() en cada columna que debería ser una clave: ¿de verdad hay una por fila? Anota todo lo raro, como un estado que no esperabas, un precio de 0 o una fecha guardada como texto. Cinco minutos aquí suelen ahorrar una hora de depuración confusa después, y te dan una lista corta de preguntas para quien sea dueño de los datos.
Errores comunes
"Una Series y un DataFrame con una columna son lo mismo"
Se ven igual al imprimirse y se comportan distinto. Una Series no tiene columnas de las que elegir, así que s[['a', 'b']] significa otra cosa; un DataFrame de una columna sigue siendo una tabla con la que puedes seguir trabajando. Si un método se queja de "no attribute", comprueba cuál de los dos tienes con type(x), y usa corchetes dobles siempre que quieras conservar una tabla.
"count() me dice cuántas filas hay"
count() cuenta los valores presentes. En una columna con datos que faltan es menor que el número de filas, y la diferencia es exactamente el número de vacíos. Para "cuántas filas" usa len o shape[0]. Para "cuántas diferentes" usa nunique(). Elegir mal da un número plausible, lo cual es peor que un error.
"Si los datos cargaron sin errores, están bien"
pandas cargará sin quejarse una columna de fechas como texto, un precio con signo de moneda como texto y una clave con duplicados. Nada de eso lanza un error. Una carga limpia significa que el archivo se pudo leer, no que los datos sean correctos. El primer vistazo es cómo descubres la diferencia.
Ponte a prueba
Una pregunta. Al responderla, la lección queda marcada en el mapa; nunca bloquea un nivel.
No del todo. Es al revés. len(orders) cuenta filas, que son pedidos, y nunique() cuenta clientes distintos.Prueba otra respuesta.
Correcto. len cuenta cada fila de pedido, mientras que nunique() cuenta cada cliente una vez, sin importar cuántos pedidos hizo. Menos clientes que pedidos significa compradores que repiten.
No del todo. Los valores que faltan los revelan count() e isna(). nunique() cuenta valores distintos y no dice nada de los que faltan.Prueba otra respuesta.
No del todo. Responden preguntas distintas, así que solo coinciden cuando cada cliente pidió exactamente una vez.Prueba otra respuesta.
Lección hecha: ya está marcada en el mapa.