Organizar datos con pandas I¶
In [1]:
import pandas as pd
import numpy as np
Multi-índice en dataframe¶
Crear un dataframe con multi-índice¶
Los dataframes pueden tener varios índices y varios nombres de columna, para esto se usa la clase de pandas MultiIndex. Estos se pueden crear a partir de una lista de tuplas, con el método drom_tuples, donde cada tupla contiene los nombres de cada columna o a partir de una combinación entre varias tuplas con el método from_product
In [2]:
columns = pd.MultiIndex.from_tuples([('A', 'positivo'), ('B', 'positivo'),
('A', 'negativo'), ('B', 'negativo'),
('O', 'positivo')],
names=['tipo', 'Rh'])
index = pd.MultiIndex.from_product([('menor', 'adulto'),('hombre', 'mujer')],
names=['edad', 'sexo'])
df = pd.DataFrame(np.random.randn(4,5), columns=columns, index=index)
df
Out[2]:
| tipo | A | B | A | B | O | |
|---|---|---|---|---|---|---|
| Rh | positivo | positivo | negativo | negativo | positivo | |
| edad | sexo | |||||
| menor | hombre | -1.807191 | -1.048591 | 0.458959 | 0.349050 | 0.682837 |
| mujer | -0.769500 | -0.541011 | -0.628476 | -0.847258 | -0.576029 | |
| adulto | hombre | 0.083071 | 0.346534 | 1.641367 | 0.563324 | 0.806927 |
| mujer | -1.183561 | 0.254588 | 0.546878 | 1.816080 | 1.309236 |
Obtener información de un dataframe multi-índex¶
Columnas¶
Para obtener la información de una columna se usa el formato corriente, dataframe[nombre_col], siempre y cuando el nombre de la columna pertenezca a una columna de primer nivel, es decir, la primera fila de nombres de columnas.
In [3]:
df['A']
Out[3]:
| Rh | positivo | negativo | |
|---|---|---|---|
| edad | sexo | ||
| menor | hombre | -1.807191 | 0.458959 |
| mujer | -0.769500 | -0.628476 | |
| adulto | hombre | 0.083071 | 1.641367 |
| mujer | -1.183561 | 0.546878 |
Para obtener información de las columnas de otros niveles, se debe referir primero la columna de primer nivel y luego a las de los niveles siguientes, en órden jerárquico.
In [4]:
df['B', 'positivo']
Out[4]:
edad sexo
menor hombre -1.048591
mujer -0.541011
adulto hombre 0.346534
mujer 0.254588
Name: (B, positivo), dtype: float64
Filas¶
In [5]:
df.loc['adulto']
Out[5]:
| tipo | A | B | A | B | O |
|---|---|---|---|---|---|
| Rh | positivo | positivo | negativo | negativo | positivo |
| sexo | |||||
| hombre | 0.083071 | 0.346534 | 1.641367 | 0.563324 | 0.806927 |
| mujer | -1.183561 | 0.254588 | 0.546878 | 1.816080 | 1.309236 |
In [6]:
df.loc['adulto', 'mujer']
Out[6]:
tipo Rh A positivo -1.183561 B positivo 0.254588 A negativo 0.546878 B negativo 1.816080 O positivo 1.309236 Name: (adulto, mujer), dtype: float64
Por posición:
In [7]:
df.iloc[0]
Out[7]:
tipo Rh A positivo -1.807191 B positivo -1.048591 A negativo 0.458959 B negativo 0.349050 O positivo 0.682837 Name: (menor, hombre), dtype: float64
In [8]:
df.iloc[0, 1]
Out[8]:
-1.0485906955417377
Slice (seleccionar secciones del dataframe)¶
In [9]:
df
Out[9]:
| tipo | A | B | A | B | O | |
|---|---|---|---|---|---|---|
| Rh | positivo | positivo | negativo | negativo | positivo | |
| edad | sexo | |||||
| menor | hombre | -1.807191 | -1.048591 | 0.458959 | 0.349050 | 0.682837 |
| mujer | -0.769500 | -0.541011 | -0.628476 | -0.847258 | -0.576029 | |
| adulto | hombre | 0.083071 | 0.346534 | 1.641367 | 0.563324 | 0.806927 |
| mujer | -1.183561 | 0.254588 | 0.546878 | 1.816080 | 1.309236 |
In [10]:
df.iloc[1:3]
Out[10]:
| tipo | A | B | A | B | O | |
|---|---|---|---|---|---|---|
| Rh | positivo | positivo | negativo | negativo | positivo | |
| edad | sexo | |||||
| menor | mujer | -0.769500 | -0.541011 | -0.628476 | -0.847258 | -0.576029 |
| adulto | hombre | 0.083071 | 0.346534 | 1.641367 | 0.563324 | 0.806927 |
General¶
Para obtener información sea de filas o columnas de cualquier nivel se usa el método xs. Se especifica el nombre de la columna y el nombre del nivel al que pertenece, para buscar por columna se agrega axis=1.
In [11]:
df.xs('mujer', level='sexo')
Out[11]:
| tipo | A | B | A | B | O |
|---|---|---|---|---|---|
| Rh | positivo | positivo | negativo | negativo | positivo |
| edad | |||||
| menor | -0.769500 | -0.541011 | -0.628476 | -0.847258 | -0.576029 |
| adulto | -1.183561 | 0.254588 | 0.546878 | 1.816080 | 1.309236 |
In [12]:
df.xs('negativo', level='Rh', axis=1)
Out[12]:
| tipo | A | B | |
|---|---|---|---|
| edad | sexo | ||
| menor | hombre | 0.458959 | 0.349050 |
| mujer | -0.628476 | -0.847258 | |
| adulto | hombre | 1.641367 | 0.563324 |
| mujer | 0.546878 | 1.816080 |
Si se quiere mantener la información de los otros niveles a los que pertenece esta información se usa el argumento drop_level=False
In [13]:
df.xs('negativo', level='Rh', axis=1 , drop_level=False)
Out[13]:
| tipo | A | B | |
|---|---|---|---|
| Rh | negativo | negativo | |
| edad | sexo | ||
| menor | hombre | 0.458959 | 0.349050 |
| mujer | -0.628476 | -0.847258 | |
| adulto | hombre | 1.641367 | 0.563324 |
| mujer | 0.546878 | 1.816080 |
Stack¶
El método stack permite reordenar los datos que tienen iguales atributos con igual nombre de columna en el dataframe. Por ejemplo si se tienen algún tipo de resultados para varios tipos de sangre, los tipos pueden ser diferentes pero pueden compartir el Rh, ese sería un atributo en común. También es uno de los métodos para manipular dataframe con varios nombres de columna.
In [14]:
# Si no se le indica los nombres de columna que convertirá en índice este
# toma el último nivel de columna en este caso "tipo" es el primer nivel
# y "Rh" el segundo.
df.stack()
Out[14]:
| tipo | A | B | O | ||
|---|---|---|---|---|---|
| edad | sexo | Rh | |||
| menor | hombre | negativo | 0.458959 | 0.349050 | NaN |
| positivo | -1.807191 | -1.048591 | 0.682837 | ||
| mujer | negativo | -0.628476 | -0.847258 | NaN | |
| positivo | -0.769500 | -0.541011 | -0.576029 | ||
| adulto | hombre | negativo | 1.641367 | 0.563324 | NaN |
| positivo | 0.083071 | 0.346534 | 0.806927 | ||
| mujer | negativo | 0.546878 | 1.816080 | NaN | |
| positivo | -1.183561 | 0.254588 | 1.309236 |
In [15]:
df.stack('tipo')
Out[15]:
| Rh | negativo | positivo | ||
|---|---|---|---|---|
| edad | sexo | tipo | ||
| menor | hombre | A | 0.458959 | -1.807191 |
| B | 0.349050 | -1.048591 | ||
| O | NaN | 0.682837 | ||
| mujer | A | -0.628476 | -0.769500 | |
| B | -0.847258 | -0.541011 | ||
| O | NaN | -0.576029 | ||
| adulto | hombre | A | 1.641367 | 0.083071 |
| B | 0.563324 | 0.346534 | ||
| O | NaN | 0.806927 | ||
| mujer | A | 0.546878 | -1.183561 | |
| B | 1.816080 | 0.254588 | ||
| O | NaN | 1.309236 |
In [16]:
# Se convierten los dos nombres de columna a índice tomando como principal a "tipo" y
# "Rh" como una clasificación interna de este.
df_st = df.stack(level=['tipo','Rh'])
df_st
Out[16]:
edad sexo tipo Rh
menor hombre A negativo 0.458959
positivo -1.807191
B negativo 0.349050
positivo -1.048591
O positivo 0.682837
mujer A negativo -0.628476
positivo -0.769500
B negativo -0.847258
positivo -0.541011
O positivo -0.576029
adulto hombre A negativo 1.641367
positivo 0.083071
B negativo 0.563324
positivo 0.346534
O positivo 0.806927
mujer A negativo 0.546878
positivo -1.183561
B negativo 1.816080
positivo 0.254588
O positivo 1.309236
dtype: float64
In [17]:
# Ahora "tipo" como una clasificación interna de "Rh"
df.stack(level=['Rh','tipo'])
Out[17]:
edad sexo Rh tipo
menor hombre negativo A 0.458959
B 0.349050
positivo A -1.807191
B -1.048591
O 0.682837
mujer negativo A -0.628476
B -0.847258
positivo A -0.769500
B -0.541011
O -0.576029
adulto hombre negativo A 1.641367
B 0.563324
positivo A 0.083071
B 0.346534
O 0.806927
mujer negativo A 0.546878
B 1.816080
positivo A -1.183561
B 0.254588
O 1.309236
dtype: float64

