Se importa la biblioteca pandas, para disponer de todos los objetos aquí definidos:
In [46]:
import pandas as pd
# importar numpy para usarlo en los ejemplos
import numpy as np
Un DataFrame es una generalización del concepto de Serie. Contiene un índice (numérico, nominal, fechas, etc.) y varias series cuyos datos se 'alinean' de acuerdo con los índices. Se puede asimilar al concepto de una tabla de varias columnas, donde los índices referencian las filas y los títulos de las columnas las series. En el lenguaje del aprendizaje de máquina a las columnas se les denomina características (features) del dataset.
Siendo una colección de series, una primera forma de instanciar un DataFrame es a partir de varias series, por ejemplo:
In [47]:
# Se crean un par de series. Observar que no es necesario que los indices coincidan
s1 = pd.Series(np.random.randn(4), index=['a', 'b', 'c', 'd'])
s2 = pd.Series(np.random.randn(4), index=['b', 'c', 'd', 'e'])
# Se crea un diccionario con las 2 columnas (Series)
dict = { 'one': s1, 'two': s2 }
# Se crea un objeto DataFrame a partir de estos datos
df1 = pd.DataFrame(dict)
df1
Out[47]:
Observar que a los indices no presentes en alguna de las series se les asigna el valor NaN (Not a Number)
Otra alternativa es crear el DataFrame a partir de un ndarray de numpy. En este caso los nombres de las columnas se deben especificar por medio del parametro columns. Por ejemplo:
In [48]:
df2 = pd.DataFrame( np.random.randn(7,4), columns=[ 'arbol', 'fruta', 'flor', 'raiz' ] )
df2
Out[48]:
Se puede crear a partir de un diccionario de listas o de ndarrays. El argumento index permite especificar los indices de la tabla.
In [49]:
dict = {'one' : [1., 2., 3., 4.],
'two' : [4., 3., 2., 1.]}
df3 = pd.DataFrame(dict, index=['qwe','rty','uio','pas'])
df3
Out[49]:
o asi mismo de una lista de diccionarios. El argumento index permite especificar los indices de la tabla.
In [50]:
listdict = [ {'b':1,'c':2,'d':3}, {'a':1.1,'c':1.2,'d':1.3}, {'c':2.1,'d':2.2,'b':2.2}, {'a':0,'b':0.1,'c':0.2,'d':0.3} ]
df4 = pd.DataFrame(listdict, index=['2017-10-01','2017-11-01','2017-12-01','2018-01-01'])
df4
Out[50]:
Observar en el ejemplo anterior como los datos se alinean por los nombres de las columnas.
In [51]:
# Tipo de dato de cada columna
df4.dtypes
Out[51]:
In [52]:
# Los valores del dataframe. Observar que retorna un ndarray
df3.values
Out[52]:
In [53]:
# Nombres de las columnas
df4.columns
Out[53]:
In [54]:
# Indices de la tabla
df4.index
Out[54]:
In [55]:
# Esta vacia la estructura?
df4.empty
Out[55]:
In [56]:
# Obtener el tamaño del DataFrame
df4.size
Out[56]:
In [57]:
# Obtener la forma del DataFrame
df4.shape
Out[57]:
Se puede utilizar el método .get o la notación de indices, por ejemplo:
In [58]:
df3.get('one')
Out[58]:
In [59]:
df3['one']
Out[59]:
Se puede recuperar un subconjunto de columnas
In [60]:
df4[ ['b','c'] ]
Out[60]:
Recuperar un subconjunto de filas (índices)
In [61]:
df4.loc[ ['2017-12-01', '2017-10-01'], :]
Out[61]:
O que tal un subconjunto de filas y de columnas
In [62]:
df4.loc[ ['2017-12-01', '2017-10-01'], ['d','b'] ]
Out[62]:
Tambien es posible referenciar los elementos del DataFrame por el numero de fila y columna que les corresponde
In [63]:
df4.iloc[0,0], df4.iloc[2,3]
Out[63]:
Por rangos de numeros de filas o de columnas
In [64]:
df2.iloc[5:,:]
Out[64]:
In [65]:
df2.iloc[3:,:2]
Out[65]:
In [66]:
df2.iloc[4:6, 1:2]
Out[66]:
Para asignar valores a una celda del dataframe, se puede utilizar .at con los nombres de indices y columnas, o .iat con las posiciones numericas correspondientes
In [67]:
df2.at[4,'fruta'] = 555
df2.iat[4,0] = 666
df2.loc[4,:]
Out[67]:
Hacer una copia de un DataFrame
In [68]:
df5 = df4.copy()
df5
Out[68]:
Reemplazar los NaN por un valor deseado. El parametro inplace=True hace que se modifique el dataframe, en lugar de devolver una copia con los cambios.
In [69]:
df5.fillna(value=-999, inplace=True)
df5
Out[69]:
Otra alternativa para manejar la presencia de NaNs es suprir las filas,columnas donde aparezcan
In [70]:
df5 = df4.copy()
df5.dropna(inplace=True)
df5
Out[70]:
Para eliminar algunas filas del DataFrame se utiliza el método .drop
In [71]:
df4.drop(['2017-12-01', '2017-11-01'])
Out[71]:
Observar en el ejemplo anterior que toda fila o toda columna que contenga un NaN es eliminada.
Se pueden recuperar los elementos del comienzo o del final del DataFrame
In [72]:
df4.head(2)
Out[72]:
In [73]:
df4.tail(3)
Out[73]:
En forma similar a como lo permiten las series es posible indexar los elementos de un DataFrame usando condiciones lógicas. Por ejemplo:
In [74]:
df4[ df4>2 ]
Out[74]:
In [75]:
df4.isnull()
Out[75]:
In [76]:
# Otra forma de hacer el .fillna
df4[ df4.isnull() ] = 0
df4
Out[76]:
In [77]:
# .all aplica la condicion booleana a todos los elementos de cada columna
(df4>0).all()
Out[77]:
In [78]:
# .any comprueba la condicion boolean si al menos un elemento de cada serie la cumple
(df4==0).any()
Out[78]:
Para DataFrames cuyos elementos son numéricos, se dispone de todos los metodos para realizar las operaciones aritmeticas estandar: .add .sub .mul .div .pow .mod .abs .dot . Asi mismo, se pueden utilizar los operadores sobrecargados: + - * / **
In [79]:
df5**2 - df4/2
Out[79]:
Los operadores relacionales se encuentran disponibles como métodos o a través de los operadores sobrecargados. Los métodos son .eq .ne .ge .gt .le .lt y sus correspondientes operadores == != >= > <= <
In [85]:
df4<=df4**2
Out[85]:
Las operaciones estadísticas con un DataFrame son: .describe .count .mix .max .mean .median .mode .var .std .cov .corr .sem
In [86]:
df4.describe()
Out[86]:
In [87]:
df4.mean()
Out[87]:
In [88]:
df4.var()
Out[88]:
In [89]:
df4.cov()
Out[89]:
Notar que efectivamente la diagonal de la matriz de covarianza son las varianzas
Salvar, recupear un DataFrame desde un archivo separado por comas
In [90]:
df4.to_csv('Dataframe4.csv')
df6 = pd.read_csv('Dataframe4.csv', index_col=0)
df6
Out[90]:
Se puede obtener la grafica de las series que componen el DataFrame en MatPlotLib
In [91]:
import matplotlib.pyplot as plt
df6.plot()
plt.show()
Obtener el histograma de cada serie
In [92]:
df6.hist()
plt.show()
Pandas también ofrece métodos para leer tablas de Excel. Para este fin se debe tener instalado el módulo xlrd.
In [93]:
t = pd.read_excel('titanic.xls')
t.shape
Out[93]:
In [95]:
t.head()
Out[95]:
La operación join permite combinar dos dataframes alineando sus indices. Un left-join preserva los índices del DataFrame izquierdo, un right-join preserva los índices del DataFrame derecho, un inner-join preserva la intersección de índices de ambos DataFrames y el outer-join preserva la union de los índices.
Considere los siguientes DataFrames que no coinciden en todos sus índices:
In [97]:
indices = np.arange( '2017-01-01', '2017-01-05', dtype=np.datetime64 )
df1 = pd.DataFrame(
{ 'col1':pd.Series([10,20,30,40], index=indices),
'col2':pd.Series([50,60,70,80], index=indices) } )
df1
Out[97]:
In [100]:
df2 = pd.DataFrame(
{ 'col3':pd.Series([70,80,90,100], index=np.arange( '2017-01-02', '2017-01-06', dtype=np.datetime64 ) ) } )
df2
Out[100]:
Los distintos tipos de join serían
In [102]:
left = df1.join(df2)
left
Out[102]:
In [105]:
right = df1.join(df2, how='right')
right
Out[105]:
In [107]:
inner = df1.join(df2, how='inner')
inner
Out[107]:
In [109]:
outer = df1.join(df2, how='outer')
outer
Out[109]:
La operación de concatenación permite agregar filas a una tabla, alineando las columnas. Acepta una lista de DataFrames a concatenar.
In [111]:
pd.concat( [df1,df2] )
Out[111]:
In [113]:
indices = np.arange( '2017-01-05', '2017-01-08', dtype=np.datetime64 )
df3 = pd.DataFrame(
{ 'col1':pd.Series([41,42,43], index=indices),
'col2':pd.Series([81,82,83], index=indices) } )
df3
Out[113]:
In [115]:
pd.concat( [df1,df3] )
Out[115]:
La operación append también realiza una función similar a la concatenación
In [117]:
df1.append([df2,df3])
Out[117]:
La operación merge es una generalización del join donde se utiliza un atributo cualquiera para efecto de alinear las filas de las tablas. Los índices se ignoran y son descartados por la operación merge.
In [118]:
indices = np.arange( '2017-01-01', '2017-01-05', dtype=np.datetime64 )
df1 = pd.DataFrame(
{ 'col1' :pd.Series([10,20,30,40], index=indices),
'col2' :pd.Series([50,60,70,80], index=indices),
'llave':pd.Series([1,2,3,4], index=indices) } )
df1
Out[118]:
In [119]:
indices = np.arange( '2017-01-02', '2017-01-06', dtype=np.datetime64 )
df2 = pd.DataFrame(
{ 'col3' :pd.Series([70,80,90,100], index=indices ),
'llave':pd.Series([2,1,4,3], index=indices) } )
df2
Out[119]:
In [120]:
pd.merge(df1, df2, on='llave')
Out[120]: