Cómo iterar sobre columnas del marco de datos de pandas para ejecutar la regresión

187

Estoy seguro de que esto es simple, pero como un novato completo en Python, tengo problemas para descubrir cómo iterar sobre las variables en un pandasmarco de datos y ejecutar una regresión con cada una.

Esto es lo que estoy haciendo:

all_data = {}
for ticker in ['FIUIX', 'FSAIX', 'FSAVX', 'FSTMX']:
    all_data[ticker] = web.get_data_yahoo(ticker, '1/1/2010', '1/1/2015')

prices = DataFrame({tic: data['Adj Close'] for tic, data in all_data.iteritems()})  
returns = prices.pct_change()

Sé que puedo ejecutar una regresión como esta:

regs = sm.OLS(returns.FIUIX,returns.FSTMX).fit()

pero supongamos que quiero hacer esto para cada columna en el marco de datos. En particular, quiero regresar FIUIX en FSTMX, y luego FSAIX en FSTMX, y luego FSAVX en FSTMX. Después de cada regresión quiero almacenar los residuos.

He probado varias versiones de lo siguiente, pero debo estar equivocando la sintaxis:

resids = {}
for k in returns.keys():
    reg = sm.OLS(returns[k],returns.FSTMX).fit()
    resids[k] = reg.resid

Creo que el problema es que no sé cómo referirme a la columna de devoluciones por clave, por returns[k]lo que probablemente esté mal.

Cualquier orientación sobre la mejor manera de hacer esto sería muy apreciada. Tal vez hay un enfoque de pandas común que me falta.

itzy
fuente
1
Puede subíndice los cols de esta manera: for i in len(df): if i + 1 != len(df): # sm.OLS(returns[returns.coloumns[i]], returns[returns.columns[ i+1]]), fit()os similar
EdChum

Respuestas:

343
for column in df:
    print(df[column])
El gato no divertido
fuente
1
Parece que solo recupero el encabezado de columna cuando uso este método. Entonces, por ejemplo: print (df) me muestra los datos en las columnas del marco de datos, pero para c en df: print (c) solo imprime el encabezado, no los datos.
user1761806
55
Ok ignórame - estaba haciendo imprimir (columna) no imprimir (df [columna])
usuario1761806
14
¡Cuidado con las columnas con el mismo nombre!
freethebees
44
Es agradable y conciso. Sin for x in dfembargo, esperaría iterar sobre filas. : - /
Eric Duminil
77
for idx, row in df.iterrows()itera sobre filas. Dado que las operaciones colbasadas están vectorizadas, es natural que la iteración principal sea sobre columnas :)
The Unfun Cat
69

Puedes usar iteritems():

for name, values in df.iteritems():
    print('{name}: {value}'.format(name=name, value=values[0]))
mdh
fuente
33

Esta respuesta es iterar sobre las columnas seleccionadas , así como todas las columnas en un DF.

df.columnsda una lista que contiene todos los nombres de las columnas en el DF. Ahora eso no es muy útil si desea iterar sobre todas las columnas. Pero resulta útil cuando desea iterar sobre columnas de su elección solamente.

Podemos usar la división de la lista de Python fácilmente para cortar columnas df. según nuestras necesidades. Por ejemplo, para iterar sobre todas las columnas excepto la primera, podemos hacer:

for column in df.columns[1:]:
    print(df[column])

De manera similar, para iterar sobre todas las columnas en orden inverso, podemos hacer:

for column in df.columns[::-1]:
    print(df[column])

Podemos iterar sobre todas las columnas de muchas maneras geniales usando esta técnica. También recuerde que puede obtener los índices de todas las columnas fácilmente usando:

for ind, column in enumerate(df.columns):
    print(ind, column)
Abhinav Gupta
fuente
21

Puede indexar las columnas del marco de datos por posición usando ix.

df1.ix[:,1]

Esto devuelve la primera columna, por ejemplo. (0 sería el índice)

df1.ix[0,]

Esto devuelve la primera fila.

df1.ix[:,1]

Este sería el valor en la intersección de la fila 0 y la columna 1:

df1.ix[0,1]

y así. Entonces puede enumerate() returns.keys():y usar el número para indexar el marco de datos.

PINCHAZO
fuente
8
ixestá en desuso, useiloc
Yohan Obadia
8

Una solución alternativa es transponer DataFramee iterar sobre las filas.

for column_name, column in df.transpose().iterrows():
    print column_name
kdauria
fuente
44
La transposición es bastante cara :)
The Unfun Cat
Puede ser costoso, pero esta es una gran solución para marcos de datos relativamente pequeños. Gracias kdauria!
elPastor
5

Usando la comprensión de la lista, puede obtener todos los nombres de columnas (encabezado):

[column for column in df]

MEhsan
fuente
2
Versión más corta: list(df.columns)o[c for c in df]
The Unfun Cat
4

Según la respuesta aceptada , si también se desea un índice correspondiente a cada columna :

for i, column in enumerate(df):
    print i, df[column]

El df[column]tipo anterior es Series, que simplemente se puede convertir en numpy ndarrays:

for i, column in enumerate(df):
    print i, np.asarray(df[column])
Ingeniero libre de herpes
fuente
3

Llego un poco tarde, pero así es como hice esto. Los pasos:

  1. Crea una lista de todas las columnas
  2. Use itertools para tomar combinaciones x
  3. Agregue cada valor cuadrado R de resultado a un marco de datos de resultados junto con la lista de columnas excluidas
  4. Ordene el resultado DF en orden descendente de R al cuadrado para ver cuál es el mejor ajuste.

Este es el código que usé en DataFrame llamado aft_tmt. Siéntase libre de extrapolar a su caso de uso.

import pandas as pd
# setting options to print without truncating output
pd.set_option('display.max_columns', None)
pd.set_option('display.max_colwidth', None)

import statsmodels.formula.api as smf
import itertools

# This section gets the column names of the DF and removes some columns which I don't want to use as predictors.
itercols = aft_tmt.columns.tolist()
itercols.remove("sc97")
itercols.remove("sc")
itercols.remove("grc")
itercols.remove("grc97")
print itercols
len(itercols)

# results DF
regression_res = pd.DataFrame(columns = ["Rsq", "predictors", "excluded"])

# excluded cols
exc = []

# change 9 to the number of columns you want to combine from N columns.
#Possibly run an outer loop from 0 to N/2?
for x in itertools.combinations(itercols, 9):
    lmstr = "+".join(x)
    m = smf.ols(formula = "sc ~ " + lmstr, data = aft_tmt)
    f = m.fit()
    exc = [item for item in x if item not in itercols]
    regression_res = regression_res.append(pd.DataFrame([[f.rsquared, lmstr, "+".join([y for y in itercols if y not in list(x)])]], columns = ["Rsq", "predictors", "excluded"]))

regression_res.sort_values(by="Rsq", ascending = False)
Gaurav
fuente