En este artículo conoceremos la librería Pandas, que es fundamental en Python para el análisis de datos, y veremos como extraer datos de un dataframe.
Pandas, parte practica
Pandas nos hace la vida un poco más fácil.¶
Muchos estamos familiarizados con Excel y con sus hojas de cálculos pues son ampliamente utilizadas para almacenar y manipular datos, especialmente numéricos, y hacer cálculos.
En Python tenemos varias librerías para manipular todo tipo de datos, pero una es especialmente eficiente para las series temporales, Pandas.
Pandas tiene dos objetos básicos las series, que son vectores indexados y los dataframes, que son matrices n-dimensionales indexadas. Podemos pensar en un dataframe como una hoja de calculo de Excel supervitaminada.
Una serie temporal es una secuencia de datos tomados en determinados momentos ordenados cronológicamente. Por ejemplo la cotización de cierre de una acción, tenemos una sucesión de valores medidos al final de la sesión de cada día. En análisis financiero prácticamente tratamos con series temporales casí todo el tiempo, y Pandas nos hace la vida mucho mas fácil.
De hecho Pandas fue desarrollada inicialmente por Wes McKinney cuando trabajaba en un hedge found, AQR Capital Management, y posteriormente liberada como open source.
Esta librería tiene un gran número de funciones para realizar cálculos y manipulaciones de series y dataframes, y se ha originado un ecosistema al ser usada como base por otras librerías de terceros, que hacen uso de estos objetos y sus funciones.
Si has instalado Anaconda para usar Python, el módulo de Pandas ya viene preinstalado. Si no es así puedes instalarlo usando conda, basta con ejecutar en el terminal de comandos:
conda install pandas
o bien usando pip:
pip install pandas
Dataframes¶
Un DataFrame de Pandas es una matriz ordenada que puede contener cualquier tipo de datos. Se ordena en columnas, que deben contener siempre un mismo tipo de dato, y en filas que generan un indice.
Para practicar con los dataframes vamos a usar series temporales de cotizaciones diarias de acciones. Para lo cual nos descargaremos los datos históricos.
Pandas Datareader es un módulo asociado a Pandas que permite descargar datos desde distintas fuentes.
Sin embargo, debido a que Yahoo descontinuó su API para datos financieros, para poder descarga desde Yahoo Finance correctamente, utilizaremos el módulo Fix Yahoo Finance. Si no lo tienes instalado puedes instalarlo con :
pip install fix-yahoo-finance
Vamos a comenzar importando esos dos módulos. Importamos Pandas y para simplificar le asignamos el nombre pd, igual hacemos con Fix Yahoo Finance.
import pandas as pd
import fix_yahoo_finance as yf
Descargaremos el histórico diario de Santander y BBVA desde principios de 2008 hasta final de 2018, once años. Para ello pasaremos como parámetros los tickers de los valores y las fechas de inicio y fin. Los tickers para otros valores se pueden localizar en la página de Yahoo Finance.
En un futuro artículo hablaremos sobre las fuentes de datos financieros y sus API, pero de de momento nos bastará con saber como bajar los datos que necesitamos para estudiar los dataframe de Pandas.
start = '2008-01-01'
end = '2018-12-31'
tickers=['SAN.MC', 'BBVA.MC']
san = yf.download(tickers[0], start=start, end=end)
bbva = yf.download(tickers[1], start=start, end=end)
Lo que recibimos en la variable san es un DataFrame de Pandas, una matriz de dos dimensiones, como dijimos algo similar al un hoja de calculo de Excel.
Vamos a ver usando el método head() las cinco primeras lineas del dataframe san.
san.head()
Y con tail() las cinco últimas de bbva.
bbva.tail()
Vamos a usar la función de Pandas describe(), que nos dará un resumen estadístico de los datos contenidos en el dataframe. Lo que este método nos devuelve es un nuevo dataframe con los datos agregados.
san.describe()
bbva.describe()
Vemos que tanto en este caso, como al usar head() y tail() no hemos aplicado la función y pasado entre paréntesis el dataframe como un parámetros, sino que tras el nombre del dataframe con un punto pasamos la función. Esto es debido a que describe() es un método del objeto dataframe, y ya lo toma como parámetro. Es especialmente útil y permite el encadenado de métodos, es decir ir agregando funciones que toman el resultado de la anterior como parámetro.
Otro método que nos proporciona información resumida es info().
san.info()
bbva.info()
Revisamos las dimensiones de cada dataframe, vemos que tienen dos dimensiones, que reflejan las filas y las columnas.
2810 filas correspondientes a los días de cotización, y 6 columnas para los distintos datos.
Para ello usamos shape, que como vemos no lleva paréntesis detrás, esto es debido a que es una propiedad del dataframe y no un método del mismo.
san.shape
bbva.shape
Podemos extraer el índice y las columnas de un dataframe usando index y columns respectivamente.
El índice de nuestros dataframe son las fechas de los días cotizados.
san.index
Mientras que las columnas recogen los distintos valores de cada día cotizado.
san.columns
Observamos como en ambos casos nos muestra 6 columnas y 5 filas. Las columna Open por ejemplo contiene todos los precios de apertura de cada acción. Y las filas están precedidas por una fecha que es el índice de nuestro dataframe. Así podemos obtener datos llamándolos por su columna, su índice o por una combinación de ambos.
Extracción de datos.¶
Puede ser que nos interese solo una columna y podemos extraerla del dataframe, lo que nos devuelve es un objeto Serie de Pandas.
san['Close']
O bien solo nos interese una fecha en concreto.
bbva.loc['2018-12-31']
Vemos que para extraer una columna solo necesitamos pasar su nombre entre corchetes pero para un índice usamos el método loc. Pandas tiene diversas formas de extraer la información en función de como queramos hacerlo. Así el método loc extrae en base a la etiqueta del índice o columna, y el método iloc lo hace en función del numero ordinal que ocupa dicho índice o columna.
san.iloc[0]
Aunque para hacer una extracción por número de orden de varias filas no necesitamos usar iloc podemos hacerlo directamente.
san[100:106]
Si es útil cuando queremos hacer una extracción tanto de filas como de columnas.
san.iloc[:2,:2]
Ahora veamos el cierre ajustado y el volumen desde el 1 al 10 de noviembre de 2015.
san.loc['2015-11-01':'2015-11-10', 'Adj Close':'Volume']
Si tenemos en cuenta que lo se devuelve siempre es un dataframe o una serie, podemos encadenar varias formas de hacer extracciones.
Así por ejemplo podemos tomar primero 3 columnas por su nombre y después las diez últimas filas. En este caso no necesitamos usar iloc.
san[['Close', 'Low', 'Volume']][-10:]
O tomar dos columnas y usar el método head(). Por ejemplo para tomar los 5 primeros mínimos y máximos
san[['High','Low']].head()
Además loc cuando lo usamos sobre un índice de fechas (datetime) permite extraer usando periodos. Así si queremos extraer los datos de mayo de 2018 podemos hacer lo siguiente.
san.loc['2018-05']
Existe otro método que es mas específico como es xs, aunque es más utilizado para los dataframe multi índices. Los cuales dejaremos para mas adelante.
bbva.xs('2018-05', axis=0)
Pandas también permite hacer una extracción (slice) usando saltos, es decir tomando los valores de cada N filas. Por ejemplo podemos tomar cada 15 filas. En este caso después usamos tail() para limitar lo que se muestra a solo los 8 últimos seleccionados por facilitar la visualización.
san[::15].tail(8)
Esto puede ser utilizado incluso para invertir el orden del índice, usando un paso negativo.
bbva[::-1].head(6)
Indexación booleana¶
Otra forma de extraer datos es usando una condición y solo nos devolverá la filas que cumplan dicha condición. Así por ejemplo podemos extraer las filas en las que el cierre de Santander supero los 13 euros, comprobando que solo fueron dos.
san[san['Close']>13]
La condición puede ser tan compleja como queramos, pudiendo usar los operadores lógicos para encadenar distintos condicionales.
bbva[(bbva.Open>15) & (bbva.Volume>10**8)]
Vemos además como en el ejemplo anterior hemos llamado las columnas Open y Volume sin usar los corchetes ni las comillas. Y es que si el nombre de la columna es una sola palabra (no contiene espacios) podemos llamarla usando solo un punto, como si de una propiedad del objeto dataframe se tratara.
Esto mismo también es posible hacerlo usando el método query(). Obtendremos exactamente el mismo resultado, solo que usando una expresión contenida en una cadena de texto para realizar la búsqueda.
bbva.query('Open>15 and Volume>10**8')
Dado que los dataframes san y bbva tienen el mismo tamaño (de hecho el mismo índice por cotizar en el mismo mercado), podemos usar una condición aplicada Santander para extraer valores del BBVA. Así por ejemplo podemos ver como cotizaba BBVA cuando Santander superó los 13 euros en su precio de cierre.
bbva[san.Close>13]
Si quieres ampliar información la propia documentación oficial de Pandas explica muy detalladamente estos métodos de extracción y algún otro.
Recuerda unirte a nuestro canal en Telegram de Python Para Trading
Puedes probar y modificar el notebook usado en este artículo, descargándolo desde su enlace en Github.