Pandas fue desarrollado en el fondo de cobertura AQR por wes mckinney para permitir un análisis rápido de los datos financieros. Pandas es una extensión de NumPy que admite operaciones vectorizadas que permiten una manipulación rápida de la información financiera.
Usaré los datos de la empresa proporcionados por un Zona de pruebas para desarrolladores de Intrinio. Si desea seguir adelante, puede encontrar el código y los datos en el Analizando Alpha Github Repo.
import pandas as pd
import numpy as np
import urllib.request
url= 'https://raw.githubusercontent.com/leosmigel ...
/analyzingalpha/master/2019-09-30-data-manipulation-with-python/companies.csv'
with urllib.request.urlopen(url) as f:
companies = pd.read_csv(f, index_col='id')
companies[['name', 'sector']].head()
name sector
id
1 Apple Inc Consumer Goods
2 American Express Co Financial
3 Boeing Co Industrial Goods
4 Caterpillar Inc Industrial Goods
5 Cisco Systems Inc Technology
Cómo hacer que sus datos estén ordenados
Si bien no es necesario para estos ejemplos simples, quiero presentar Tidy Data. Cuando trabaje con grandes conjuntos de datos, y especialmente para el análisis factorial, querrá hacer su vida más fácil y ordenar su conjunto de datos usando pandas.melt. Hace que los datos sean más fáciles de analizar y, por lo general, más eficaces. Para aquellos que estén interesados, hay un gran artículo sobre medio en Poner en orden el conjunto de datos en Python.
Operaciones de cadenas en Pandas
A menudo, necesitaremos manipular datos de cadenas que tienen un formato incorrecto. pandas proporciona [vectorized string operations/python-for-finance#vectorization). For most string operations, you’ll need to be familiar with regular expressions.
Let’s perform an example extract operation by smushing some of our existing data together.
companies_smushed = pd.DataFrame()
companies_smushed['sector_employees'] = empresas['sector'] + \ empresas['employees'].astype(str) print(empresas[['sector', 'employees']].head()) print(companies_smushed.head()) empresas_smushed = empresas_smushed['sector_employees'].str.extract(r'(\D+)(\d+)') empresas_aplastadas.cabeza()
sector employees
0 Consumer Goods 132000
1 Financial 59000
2 Industrial Goods 153027
3 Industrial Goods 104000
4 Technology 74200
sector_employees
0 Consumer Goods 132000
1 Financial 59000
2 Industrial Goods 153027
3 Industrial Goods 104000
4 Technology 74200
0 1
0 Consumer Goods 132000
1 Financial 59000
2 Industrial Goods 153027
3 Industrial Goods 104000
4 Technology 74200
Operaciones de agrupación: dividir-aplicar-combinar
Las operaciones de agrupación se pueden dividir en tres pasos:
Antes de usar pandas para agrupar y modificar nuestros datos, veamos cómo podríamos lograr contar el número de empresas en cada sector usando python.
sector_count = {}
for sector in companies['sector']:
if sector_count.get(sector):
sector_count.update({sector: sector_count[sector] + 1})
else:
sector_count.update({sector: 1})
print(sector_count)
{'Consumer Goods': 4,
'Financial': 5,
'Industrial Goods': 5,
'Technology': 5,
'Basic Materials': 2,
'Services': 3,
'Healthcare': 4}
Agrupamiento
pandas.Dataframe.groupby nos da una mejor manera de agrupar datos. groupby devuelve un objeto DataFrameGroupBy o SeriesGroupBy. Estos objetos se pueden considerar como un grupo. Puede ver a continuación que sector_group.groups devuelve un diccionario de pares clave/valor que son sectores y sus filas asociadas. Vea a continuación que el grupo financiero contiene filas ([1, 6, 8, 14, 23]) respectivamente.
sector_group = companies.groupby(by='sector')
print(sector_group)
print(sector_group.groups)
print(sector_group.get_group('Financial'))
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7f2a7853b828>
{'Basic Materials': Int64Index([5, 27], dtype='int64'),
'Consumer Goods': Int64Index([0, 15, 20, 22], dtype='int64'),
'Financial': Int64Index([1, 6, 8, 14, 23], dtype='int64'),
'Healthcare': Int64Index([13, 18, 21, 24], dtype='int64'),
'Industrial Goods': Int64Index([2, 3, 7, 12, 17], dtype='int64'),
'Services': Int64Index([9, 16, 26], dtype='int64'),
'Technology': Int64Index([4, 10, 11, 19, 25], dtype='int64')}
id name ... industry_group employees
1 2 American Express Co ... Credit Services 59000
6 25 Visa Inc ... Credit Services 17000
8 8 Goldman Sachs Group Inc ... Investment Brokerage - National 36600
14 13 JPMorgan Chase & Co ... Money Center Banks 256105
23 22 Travelers Companies Inc ... Property & Casualty Insurance 30400
[5 rows x 7 columns]
Para mostrar que el objeto groupby es solo un modelo, podemos replicar get_group usando iloc.
print(companies.iloc[[1,6,8,14,23],[1,5,6]])
name industry_group employees
1 American Express Co Credit Services 59000
6 Visa Inc Credit Services 17000
8 Goldman Sachs Group Inc Investment Brokerage - National 36600
14 JPMorgan Chase & Co Money Center Banks 256105
23 Travelers Companies Inc Property & Casualty Insurance 30400
En resumen, groupby crea un modelo que nos permite ejecutar muchas operaciones útiles en el grupo. Usar un objeto groupby es eficiente ya que nos permite tener una relación de uno a muchos con respecto al cálculo de valores de grupo.
Alternativamente, podemos usar el poder de Pandas y usar la indexación booleana y un método de agregación para devolver el número de empresas en cada sector.
Agregación
La agregación toma los valores y devuelve un valor de una dimensión menor. Por ejemplo, una función que toma una serie y devuelve un único valor escalar. Cada agregación de GroupBy, ya sea implícita o explícitamente, tiene una columna de agrupación, una columna de agregación y una columna de función. Las funciones de agregación comunes se muestran a continuación: Función Descripción media () Calcular la media de los grupos suma () Calcular la suma de los valores del grupo tamaño () Calcular los tamaños de los grupos contar () Calcular el recuento de los grupos td () Desviación estándar de los grupos var () Calcular la varianza de los grupos sem () Error estándar del media de gruposdescribe()Genera estadísticas descriptivasfirst()Calcula el primero de los valores del grupolast()Calcula el último de los valores del gruponth()Toma el valor enésimo, o un subconjunto si n es una listamin()Calcula el mínimo de los valores del grupomax()Calcula el máximo de los valores del grupo
print(sector_group.size())
print(sector_group.size().sum())
sector
Basic Materials 2
Consumer Goods 4
Financial 5
Healthcare 4
Industrial Goods 5
Services 3
Technology 5
dtype: int64
28
También podemos agrupar por varias columnas. Observe que la función de agregación se invocó automáticamente en la columna de empleados, ya que es la única columna de tipo numérico.
companies.groupby(['sector', 'industry_group'])['employees'].sum()
sector industry_group
Basic Materials Major Integrated Oil & Gas 119600
Consumer Goods Beverages - Soft Drinks 62600
Electronic Equipment 132000
Personal Products 92000
Textile - Apparel Footwear & Accessories 73100
Financial Credit Services 76000
Investment Brokerage - National 36600
Money Center Banks 256105
Property & Casualty Insurance 30400
Healthcare Drug Manufacturers - Major 296500
Health Care Plans 300000
Industrial Goods Aerospace/Defense Products & Services 393027
Diversified Machinery 376516
Farm & Construction Machinery 104000
Services Discount, Variety Stores 2200000
Home Improvement Stores 413000
Restaurants 210000
Technology Business Software & Services 131000
Information Technology Services 350600
Networking & Communication Devices 74200
Semiconductor - Broad Line 107400
Telecom Services - Domestic 144500
Name: employees, dtype: int64
pandas.core.groupby.DataFrame.agg nos permite realizar múltiples agregaciones a la vez, incluidas las agregaciones definidas por el usuario.
def half(column):
return column.sum() / 2
def total(column):
return column.sum()
companies.groupby(['sector']).agg({'employees': [np.min, half, total]})
employees
amin half total
sector
Basic Materials 48600 59800.0 119600
Consumer Goods 62600 179850.0 359700
Financial 17000 199552.5 399105
Healthcare 69000 298250.0 596500
Industrial Goods 93516 436771.5 873543
Services 210000 1411500.0 2823000
Technology 74200 403850.0 807700
Transformación
La transformación devuelve datos manipulados en el mismo tamaño que los datos pasados. Hay muchos métodos y funciones a su disposición para transformar datos, como se muestra a continuación. Método / Función Descripción Serie. mapa Sustituir cada valor por otro Serie. aplicar Invocar una función por elementos en una serie DataFrame. rowSeries.transformInvoca una función que devuelve una serie de valores transformadosDataFrame.transformInvoca una función que devuelve un marco de datos de valores transformadospandas.meltReforma un marco de datos. Útil para graficar, operaciones vectorizadas y ordenar datos.pandas.pivotRemodelar un marco de datos. Esencialmente una operación sin fundir.
En el siguiente ejemplo, pasamos una función definida find_percent y devolvemos la serie transformada.
def find_percent(column):
return column / float(column.sum())
companies.groupby('sector').agg({'employees': 'sum'}).transform(find_percent)
employees
sector
Basic Materials 0.020003
Consumer Goods 0.060159
Financial 0.066749
Healthcare 0.099763
Industrial Goods 0.146098
Services 0.472141
Technology 0.135086
Al igual que con agg, podemos pasar múltiples funciones, incluidas funciones lambda.
companies.groupby('sector').agg({'employees':'sum'}).transform([lambda x: x / x.sum()])
employees
<lambda>
sector
Basic Materials 0.020003
Consumer Goods 0.060159
Financial 0.066749
Healthcare 0.099763
Industrial Goods 0.146098
Services 0.472141
Technology 0.135086
Si bien no podemos pasar múltiples funciones para aplicar como podemos con transform, podemos acceder a otras columnas usando apply donde estamos limitados con transform. Nuevamente, es mejor saber qué está disponible para usted y usar la mejor herramienta para el trabajo en ese momento actual.
companies.groupby('sector').apply(lambda x: x['employees'] * 2)
sector
Basic Materials 5 97200
27 142000
Consumer Goods 0 264000
15 125200
20 146200
22 184000
Financial 1 118000
6 34000
8 73200
14 512210
23 60800
Healthcare 13 270200
18 138000
21 184800
24 600000
Industrial Goods 2 306054
3 208000
7 566000
12 480000
17 187032
Services 9 826000
16 420000
26 4400000
Technology 4 148400
10 701200
11 214800
19 262000
25 289000
Name: employees, dtype: int64
Filtración
El filtro devuelve un subconjunto de los datos originales. Funciona de manera similar a la indexación booleana, excepto que en lugar de trabajar en filas individuales, funciona en grupos individuales. El filtro debe devolver un valor verdadero o falso para el grupo como un todo. El sector servicios es el único sector que cuenta con más de 1.000.000 de empleados.
companies.groupby('sector').filter(
lambda x: x['employees'].sum() > 1000000
)[['name', 'employees']]
name employees
id
9 Home Depot Inc 413000
15 McDonalds Corp 210000
27 Walmart Inc 2200000
Tablas dinamicas
Podemos producir los mismos datos en un formato diferente usando pandas.pivot_table.
companies.pivot_table(columns='sector', values='employees', aggfunc='sum')
sector Basic Materials Consumer Goods ...
employees 119600 359700
Unión de datos
Podemos unir rápidamente dos marcos de datos a través de unir, fusionar y concatenar. Merge es la función subyacente para todos los comportamientos de unión/fusión. Unirse tiene valores predeterminados ligeramente diferentes y se proporciona como un método conveniente.
Veamos un ejemplo en acción incorporando los datos de seguridad y uniéndonos en la columna de identificación.
import pandas as pd
import numpy as np
import urllib.request
url= 'https://raw.githubusercontent.com/leosmigel ...
/analyzingalpha/master/data-manipulation-with-python/securities.csv'
with urllib.request.urlopen(url) as f:
securities = pd.read_csv(f, index_col='id')
print(securities.head())
securities_companies = companies.join(securities)
securities_companies[['name', 'ticker', 'figi']].head(7)
ticker currency figi
id
1 AAPL USD BBG000B9Y5X2
2 AXP USD BBG000BCR153
3 BA USD BBG000BCSV38
4 CAT USD BBG000BF0LJ6
5 CSCO USD BBG000C3JBN9
name ticker figi
id
1 Apple Inc AAPL BBG000B9Y5X2
2 American Express Co AXP BBG000BCR153
3 Boeing Co BA BBG000BCSV38
4 Caterpillar Inc CAT BBG000BF0LJ6
5 Cisco Systems Inc CSCO BBG000C3JBN9
6 Chevron Corp CVX BBG000K4NHJ5
25 Visa Inc V BBG000PSL0X0