2017-10-05 2 views
0

Je dispose actuellement d'un processus de fenêtrage de séries temporelles, mais je me demande s'il existe une approche vectorisée en place pour des raisons de performances/ressources.Etiquettes de fenêtre PANDAS Time Series

J'ai deux listes qui ont les dates de début et de fin des fenêtres de 30 jours:

start_dts = [01.01.2014, ...] end_dts = [30.01.2014, ... ]

J'ai une base de données avec un champ appelé 'transaction_dt'. Ce que j'essaye d'accomplir est la méthode pour ajouter deux nouvelles colonnes («start_dt» et «end_dt») à chaque rangée quand le transaction_dt est entre une paire des valeurs de «start_dt» et de «end_dt». Idéalement, ceci serait vectorisé et en place si possible.

EDIT:

Comme l'a demandé voici quelques exemples de données de mon Format:

'customer_id','transaction_dt','product','price','units' 
1,2004-01-02,thing1,25,47 
1,2004-01-17,thing2,150,8 
2,2004-01-29,thing2,150,25 
+0

Ajoutez vos données d'échantillon – Wen

+0

@Wen J'ai ajouté des exemples de données dans mon format comme demandé. Merci! – Pylander

+0

vérifier ma réponse – Wen

Répondre

0

IIUC

en poursuivant en justice IntervalIndex

df2.index=pd.IntervalIndex.from_arrays(df2['Start'],df2['End'],closed='both') 
df[['End','Start']]=df2.loc[df['transaction_dt']].values 


df 
Out[457]: 
    transaction_dt  End  Start 
0  2017-01-02 2017-01-31 2017-01-01 
1  2017-03-02 2017-03-31 2017-03-01 
2  2017-04-02 2017-04-30 2017-04-01 
3  2017-05-02 2017-05-31 2017-05-01 

des données d'entrée:

df=pd.DataFrame({'transaction_dt':['2017-01-02','2017-03-02','2017-04-02','2017-05-02']}) 
df['transaction_dt']=pd.to_datetime(df['transaction_dt']) 
list1=['2017-01-01','2017-02-01','2017-03-01','2017-04-01','2017-05-01'] 
list2=['2017-01-31','2017-02-28','2017-03-31','2017-04-30','2017-05-31'] 
df2=pd.DataFrame({'Start':list1,'End':list2}) 
df2.Start=pd.to_datetime(df2.Start) 
df2.End=pd.to_datetime(df2.End) 
+0

Je reçois une erreur KeyError liée aux valeurs manquantes et plus tôt dans le rappel d'erreur tuple imbriqué slicing lié à "ne peut pas indexer avec la clé multidimensionnelle" – Pylander

0

Si vous voulez commencer et de fin, nous pouvons utiliser, Extracting the first day of month of a datetime type column in pandas:

import io 
import pandas as pd 
import datetime 

string = """customer_id,transaction_dt,product,price,units 
1,2004-01-02,thing1,25,47 
1,2004-01-17,thing2,150,8 
2,2004-01-29,thing2,150,25""" 

df = pd.read_csv(io.StringIO(string)) 

df["transaction_dt"] = pd.to_datetime(df["transaction_dt"]) 

df["start"] = df['transaction_dt'].dt.floor('d') - pd.offsets.MonthBegin(1) 
df["end"] = df['transaction_dt'].dt.floor('d') + pd.offsets.MonthEnd(1) 

df 

Retours

customer_id transaction_dt product price units start end 
0 1 2004-01-02 thing1 25 47 2004-01-01 2004-01-31 
1 1 2004-01-17 thing2 150 8 2004-01-01 2004-01-31 
2 2 2004-01-29 thing2 150 25 2004-01-01 2004-01-31 

nouvelle approche:

import io 
import pandas as pd 
import datetime 

string = """customer_id,transaction_dt,product,price,units 
1,2004-01-02,thing1,25,47 
1,2004-01-17,thing2,150,8 
2,2004-06-29,thing2,150,25""" 

df = pd.read_csv(io.StringIO(string)) 

df["transaction_dt"] = pd.to_datetime(df["transaction_dt"]) 

# Get all timestamps that are necessary 
# This assumes dates are sorted 
# if not we should change [0] -> min_dt and [-1] --> max_dt 
timestamps = [df.iloc[0]["transaction_dt"].floor('d') - pd.offsets.MonthBegin(1)] 
while df.iloc[-1]["transaction_dt"].floor('d') > timestamps[-1]: 
    timestamps.append(timestamps[-1]+datetime.timedelta(days=30)) 

# We store all ranges here 
ranges = list(zip(timestamps,timestamps[1:])) 

# Loop through all values and add to column start and end 
for ind,value in enumerate(df["transaction_dt"]): 
    for i,(start,end) in enumerate(ranges): 
     if (value >= start and value <= end): 
      df.loc[ind, "start"] = start 
      df.loc[ind, "end"] = end 
      # When match is found let's also 
      # remove all ranges that aren't met 
      # This can be removed if dates are not sorted 
      # But this should speed things up for large datasets 
      for _ in range(i): 
       ranges.pop(0) 
+0

Ceci est une bonne approche. Malheureusement, j'ai besoin pour eux d'être exactement les fenêtres de 30 jours, pas mensuellement. – Pylander

+0

@Pylander J'ai réécrit le code mais je ne peux pas vous dire à quel point c'est efficace: D –