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