2016-06-26 12 views
7

Mam dość wyrafinowany kod przewidywania z ponad 20 kolumnami i milionami danych na kolumnę za pomocą wls. Teraz używam iterrow do zapętlenia dat, a następnie w oparciu o te daty i wartości w tych datach, wyodrębnij różne rozmiary danych do obliczeń. trwa godzin do pracy w mojej produkcji, ja uprościć kod do następujących:Jak wektorować Obliczenia Pandy oparte na ostatnich x wierszy danych

import pandas as pd 
import numpy as np 
from datetime import timedelta 

df=pd.DataFrame(np.random.randn(1000,2), columns=list('AB')) 
df['dte'] = pd.date_range('9/1/2014', periods=1000, freq='D') 

def calculateC(A, dte): 
    if A>0: #based on values has different cutoff length for trend prediction 
     depth=10 
    else: 
     depth=20 
    lastyear=(dte-timedelta(days=365)) 
    df2=df[df.dte<lastyear].head(depth) #use last year same date data for basis of prediction 
    return df2.B.mean() #uses WLS in my model but for simplification replace with mean 

for index, row in df.iterrows(): 
    if index>365: 
     df.loc[index,'C']=calculateC(row.A, row.dte) 

czytałem że iterrow jest główną przyczyną, ponieważ nie jest skutecznym sposobem korzystania z Pandy i należy użyć metody wektorowej. Jednak nie mogę znaleźć sposobu na wektor w oparciu o warunki (daty, różne długości i zakres wartości). Czy istnieje sposób?

+0

Wiem, że to stare pytanie, ale to, co warto "itertuples()" jest zauważalnie szybsze niż "iterrows()". – shadowtalker

Odpowiedz

0

chciałbym spróbować pandas.DataFrame.apply (FUNC, oś = 1)

def calculateC2(row): 
    if row.name >365: # row.name is the index of the row 
     if row.A >0: #based on values has different cutoff length for trend prediction 
      depth=10 
     else: 
      depth=20 
     lastyear=(row.dte-timedelta(days=365)) 
     df2=df[df.dte<lastyear].B.head(depth) #use last year same date data for basis of prediction 
     print row.name,np.mean(df2) #uses WLS in my model but for simplification replace with mean 

df.apply(calculateC2,axis=1) 
2

Mam dobrą i złą wiadomość. Dobrą wiadomością jest to, że mam coś wektoryzowanego, że jest około 300x szybciej, ale zła wiadomość jest taka, że ​​nie mogę całkiem powtórzyć twoich wyników. Ale myślę, że powinieneś być w stanie użyć zasad tutaj, aby znacznie przyspieszyć twój kod, nawet jeśli ten kod aktualnie nie powiela twoich wyników.

df['result'] = np.where(df['A'] > 0, 
         df.shift(365).rolling(10).B.mean(), 
         df.shift(365).rolling(20).B.mean()) 

Twarda (powolny) część kodu jest taka:

df2=df[df.dte<lastyear].head(depth) 

Jednak tak długo, jak terminy są wszystkie 365 dni od siebie, można użyć kodu jak ten, który jest wektorowy i znacznie szybciej:

df.shift(365).rolling(10).B.mean() 

shift(365) zastępuje df.dte < lastyear i rolling().mean() zastępuje head().mean(). Będzie to znacznie szybsze i zużywa mniej pamięci.

Rzeczywiście, nawet jeśli daty nie są w pełni regularne, prawdopodobnie można je ponownie zmienić i uzyskać w ten sposób. Lub, w pewnym sensie, jeśli podasz datę swojemu indeksowi, można zmienić pracę na podstawie częstotliwości zamiast wierszy (np. Przesunięcie 365 dni, nawet jeśli nie jest to 365 wierszy). Dobrym pomysłem byłoby zrobienie tego "indeksu" tutaj niezależnie.

+0

Byłbym sceptycznie nastawiony do przesunięć opartych na indeksach podczas pracy z datami: http://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time – shadowtalker

+0

Zgadzam się, oczywiście, stąd moja sugestia spraw, aby data była indeksem ;-) Ale ostatecznie zależy to od danych, czy bardziej odpowiednie jest przesunięcie w rzędzie czy przesunięcie w czasie. – JohnE

Powiązane problemy