En este capítulo aprenderás una forma coherente de organizar tus datos en Python usando el principio conocido como tidy data (datos ordenados). El formato tidy data no es adecuado para todo, pero para muchos análisis y muchos datos tabulares será lo que necesitas. Llevar tus datos a este formato requiere algo de trabajo al principio, pero ese trabajo compensa a largo plazo. Una vez que tengas tidy data, pasarás mucho menos tiempo transformando datos de una representación a otra, lo que te permitirá dedicar más tiempo a las preguntas sobre los datos que te interesan.
En este capítulo, primero aprenderás la definición de tidy data y la verás aplicada a un dataset sencillo de ejemplo. Después nos adentraremos en la herramienta principal que usarás para ordenar datos: el melting (fundido). El melting te permite cambiar la forma de tus datos sin cambiar ninguno de los valores. Terminaremos con una discusión sobre datos útilmente desordenados y cómo puedes crearlos si lo necesitas.
Si este capítulo te gusta especialmente y quieres aprender más sobre la teoría subyacente, puedes consultar el artículo Tidy Data publicado en el Journal of Statistical Software.
Requisitos previos
Este capítulo usará el paquete de análisis de datos pandas.
Tidy data
Hay tres características interrelacionadas que hacen que un dataset sea tidy:
Cada variable es una columna; cada columna es una variable.
Cada observación es una fila; cada fila es una observación.
Cada valor es una celda; cada celda es un único valor.
La siguiente figura lo muestra:
¿Por qué asegurarte de que tus datos sean tidy? Hay dos ventajas principales:
Hay una ventaja general en elegir una forma coherente de almacenar los datos. Si tienes una estructura de datos coherente, es más fácil aprender las herramientas que trabajan con ella porque tienen una uniformidad subyacente. Algunas herramientas, por ejemplo el paquete de visualización de datos seaborn, están diseñadas pensando en tidy data.
Hay una ventaja específica en colocar las variables en columnas, porque te permite aprovechar las operaciones vectorizadas de pandas (operaciones que son más eficientes).
Los tidy data no serán apropiados siempre ni en todos los casos, pero son una opción por defecto realmente muy buena para datos tabulares. Una vez que los uses por defecto, es más fácil pensar en cómo realizar las operaciones posteriores.
Dicho esto, los tidy data son geniales, pero una de las ventajas de pandas frente a otras librerías de análisis de datos es que no está demasiado atada a los tidy data y también puede manejar sin problemas tareas incómodas de manipulación de datos que no son tidy.
Hay dos problemas comunes en los datos que se importan que hacen que no sean tidy:
Una variable puede estar repartida en varias columnas.
Una observación puede estar dispersa en varias filas.
Para lo primero, necesitamos hacer “melt” de los datos anchos, con varias columnas, para convertirlos en datos largos.
Para lo segundo, necesitamos hacer unstack o pivot de las varias filas a columnas (es decir, pasar de largo a ancho).
Veremos ambos casos a continuación.
Herramientas para ordenar datos con pandas
Melt
melt() puede ayudarte a pasar de datos “más anchos” a datos “más largos”, y es una función realmente útil de recordar.
Unmelted:
first last job height weight
0 John Doe Nurse 5.5 130
1 Mary Bo Economist 6.0 150
Melted:
first
last
quantity
value
0
John
Doe
height
5.5
1
Mary
Bo
height
6.0
2
John
Doe
weight
130.0
3
Mary
Bo
weight
150.0
TipEjercicio
Realiza un melt() que use job como id en lugar de first y last.
¿Qué relación tiene esto con tidy data? A veces tendrás una variable repartida en varias columnas que querrás ordenar. Veamos este ejemplo que usa casos de tuberculosis de la Organización Mundial de la Salud.
Primero abramos los datos y veamos el inicio del archivo.
Ahora tenemos una observación por fila y una variable por columna: ¡tidy!
Una forma más sencilla de pasar de ancho a largo
Si no quieres complicarte con melt(), también existe wide_to_long(), que es muy útil para casos típicos de limpieza de datos en los que tienes datos como estos:
es decir, datos en los que hay distintas variables y periodos de tiempo a lo largo de las columnas. wide_to_long() nos permitirá indicar cuáles son los prefijos (stubnames) (‘A’, ‘B’), el nombre de la variable que siempre aparece a lo largo de las columnas (aquí, un año), los valores (aquí X) y una columna de identificador.
Stack, stack(), es un atajo para tomar un único tipo de variable de datos anchos desde las columnas y convertirla en un dataset en formato largo, pero con un índice adicional.
Unstack, unstack(), como es de esperar, hace la misma operación, pero a la inversa.
Definamos un dataframe con multiíndice para demostrarlo:
first second
bar one A 0.289982
B 1.180755
two A 0.526211
B 1.110038
baz one A -0.244239
B -0.294122
two A 0.691194
B 0.561715
foo one A -0.422054
B 0.613435
two A 0.594081
B 0.420792
qux one A 0.223132
B -0.517862
two A 0.757731
B 0.318012
dtype: float64
Esto ha creado automáticamente un índice de varios niveles, pero se puede volver a un índice numerado usando df.reset_index()
Ahora veamos unstack, pero en lugar de hacer unstack de las variables ‘A’ y ‘B’ con las que empezamos, hagamos unstack de la columna ‘first’ pasando level=0 (por defecto se hace unstack del índice más interno). Este diagrama muestra lo que ocurre:
Y aquí está el código:
df.unstack(level=0)
first
bar
baz
foo
qux
second
one
A
0.289982
-0.244239
-0.422054
0.223132
B
1.180755
-0.294122
0.613435
-0.517862
two
A
0.526211
0.691194
0.594081
0.757731
B
1.110038
0.561715
0.420792
0.318012
TipEjercicio
¿Qué ocurre si haces el unstack a level=1? ¿Y si aplicas unstack() dos veces?
Pivotar datos de largo a ancho
pivot() y pivot_table() te ayudan a ordenar datos en los que una única observación está dispersa en varias filas.
Aquí tienes un dataframe de ejemplo en el que las observaciones están repartidas en varias filas:
Los pivots son especialmente útiles para datos de series temporales, en los que operaciones como shift() o diff() se aplican normalmente suponiendo que una entrada de una fila sigue (en el tiempo) a la de arriba. Cuando hacemos shift(), a menudo queremos desplazar una sola variable en el tiempo, pero si una única observación (en este caso, una fecha) está en varias filas, la temporalidad se va a desajustar. Veamos un ejemplo.
Si simplemente ejecutamos shift() sobre lo anterior, se desplazarán juntas las variables B y A, aunque se solapan en el tiempo y son variables distintas. Por eso pivotamos a un formato más ancho (y después ya podemos desplazar en el tiempo con seguridad).
Realiza un pivot() que se aplique tanto a la columna variable como a la columna category en el ejemplo anterior, donde category se define de modo que `df[“category”] = np.random.choice([“type1”, “type2”, “type3”, “type4”], 20). (Pista: recuerda que tendrás que pasar varios objetos mediante una lista).