Manera eficiente de hacer la operación de pandas y saltar fila.

Debe haber una forma simple de hacer esto, pero me lo estoy perdiendo. Primero, imagina la situación en Excel:

  1. Tengo una columna de cambios porcentuales. (asume la columna A)
  2. En la siguiente columna (B), quiero crear una serie indexada que comience en 1000 en función del porcentaje de cambios. En Excel, lo hago por. -configuración de B1 a 1000 -set B2 a la fórmula = (1 + A2) * B1 -copie la columna hacia abajo. Sencillo.

Ahora, quiero hacer lo mismo con los pandas, y el problema es que el siguiente código hace que la matriz de destino se convierta en NaN:

import pandas as pd import numpy as np df_source = pd.DataFrame(np.random.normal(0,.05,10), index=range(10), columns=['A']) df_target = pd.DataFrame(index = df_source.index) df_target.loc[0,"A"] = 1000 # initialize target array to start at 1000 df_target["A"] = (1 + df_source) * df_target["A"].shift(1) # How to skip first row? 

La matriz de destino se convierte en NaN porque la primera fila intenta hacer referencia a un valor “fuera del dataframe”, por lo que toda la columna devuelve NaN.

Me doy cuenta de que podría recorrer filas con un bucle, saltándome la primera fila, pero esto es muy lento y no es práctico para el tamaño de los conjuntos de datos o las iteraciones que haré.

Debe haber una forma de usar las funciones de matriz pandas / numpy pero dígale que omita la primera fila en el cálculo . ¿Como hacer eso? He intentado la indexación booleana pero no puedo hacer que funcione, y tal vez haya una manera de decirle a Pandas que se salte los resultados de NaN … pero el mejor enfoque parece ser un calificador que dice “aplique este código, comenzando en la segunda fila “.

¿Que me estoy perdiendo aqui?

Editar:

Parece que mi problema es más profundo de lo que me di cuenta. La respuesta de Jezrael a continuación resuelve el problema de NA, pero creo que estoy confundido acerca de la lógica de los pandas. El código que doy arriba NO funciona porque no funciona en forma elemental. Por ejemplo, el ejemplo trivial:

 seriesdf = pd.DataFrame(index = range(10)) seriesdf['A'] = 1 seriesdf['A'].ix[1:] = 1 + seriesdf['A'].shift(1) 

da el resultado

  A 0 1 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 2 

No es un conteo ascendente como había asumido. Entonces, la pregunta es ¿cuál es la forma más eficiente de hacer este cálculo fila por fila en un dataframe de pandas? La velocidad es importante en esta aplicación, por lo que preferiría no interrumpir las filas.

Nuevo progtwigdor de Python aquí, así que tratando de resolver esto. Las respuestas que me muestran cómo aprender / descifrar cosas como esta para mí son muy apreciadas. ¡Gracias!

IIUC puede omitir la primera fila de la columna A de df_source seleccionando todas las filas sin la primera antes de ix :

 df_target["A"].ix[1:] = df_source['A'].ix[1:] + 1 print df_target A 0 1000.000000 1 0.988898 2 0.986142 3 1.009979 4 1.005165 5 1.101116 6 0.992312 7 0.962890 8 1.051340 9 1.009750 

O tal vez piensas:

 import pandas as pd import numpy as np df_source = pd.DataFrame(np.random.normal(0,.05,10), index=range(10), columns=['A']) print df_source A 0 0.039965 1 0.060821 2 -0.079238 3 -0.129932 4 0.002196 5 -0.003721 6 -0.008358 7 0.014104 8 -0.022905 9 0.014793 df_target = pd.DataFrame(index = df_source.index) #all A set to 1000 df_target["A"] = 1000 # initialize target array to start at 1000 print df_target A 0 1000 1 1000 2 1000 3 1000 4 1000 5 1000 6 1000 7 1000 8 1000 9 1000 
 df_target["A"] = (1 + df_source["A"].shift(-1))* df_target["A"] print df_target A 0 1060.820882 1 920.761946 2 870.067878 3 1002.195555 4 996.279287 5 991.641909 6 1014.104402 7 977.094961 8 1014.793488 9 NaN 

EDITAR:

Tal vez usted necesita cumsum :

 df_target["B"] = 2 df_target["C"] = df_target["B"].cumsum() df_target["D"] = df_target["B"] + df_target.index print df_target ABCD 0 1041.003000 2 2 2 1 1013.817000 2 4 3 2 948.853000 2 6 4 3 1031.692000 2 8 5 4 970.875000 2 10 6 5 1011.095000 2 12 7 6 1053.472000 2 14 8 7 903.765000 2 16 9 8 1010.546000 2 18 10 9 0.010546 2 20 11 

Creo que entiendo su problema y en estos casos, generalmente me resulta más fácil hacer una lista y agregarla al dataframe existente. Usted, por supuesto, podría hacer primero una instancia de la Serie y luego hacer cálculos.

 new_series = [0]*len(df["A"]) new_series[0] = 1000 for i,k in enumerate(dataframe["A"].ix[1:]): new_series[i] = (1 + k)*new_series[i-1] dataframe["B"] = pd.Series(new_series) 

IIRC, iloc está en desuso en futuras versiones de pandas en favor de ix

Después de repensar el problema, puede usar expresiones lambda como elementos en su dataframe

 dataframe["B"] = [lambda row: (1 + dataframe["A"].ix[row])*dataframe["B"].ix[row-1]*len(dataframe["A"]) # Above: initiate "B" with a lambda expression that is as long as "A" dataframe["B"].ix[0] = 1000 for i,k in enumerate(dataframe["B"].ix[1]): dataframe["B"].ix[i] = k(row=i) 

Estoy tratando de pensar en una forma de evitar el uso de un bucle for para este problema, pero no puedo averiguar de dónde obtener un número de fila.

Espero que esto ayude.