Uso i dati di una sfida passata del kaggle in base ai dati del pannello in un certo numero di negozi e un periodo di 2,5 anni. Ogni osservazione include il numero di clienti per una determinata data di negozio. Per ogni data di negozio, il mio obiettivo è calcolare il numero medio di clienti che hanno visitato questo negozio negli ultimi 60 giorni.Accelerazione della media degli ultimi 60 giorni nei panda
Di seguito è riportato il codice che fa esattamente ciò di cui ho bisogno. Tuttavia, dura per sempre: ci vorrebbe una notte per elaborare le righe di c.800k. Sto cercando un modo intelligente per raggiungere lo stesso obiettivo più velocemente.
Ho incluso 5 osservazioni del set di dati iniziale con le variabili rilevanti: store id (Store), Data e numero di clienti ("Clienti").
Nota:
- Per ogni riga nella iterazione, che finiscono scrivere i risultati utilizzando .loc invece di esempio row ["Lagged No of customers"] perché "row" non scrive nulla nelle celle. Mi chiedo perché sia così.
- Normalmente compro le nuove colonne usando "apply, axis = 1", quindi apprezzerei davvero qualsiasi soluzione basata su questo. Ho scoperto che "apply" funziona bene quando per ogni riga, il calcolo viene eseguito su colonne utilizzando valori allo stesso livello di riga. Tuttavia, non so come una funzione "applica" possa coinvolgere diverse righe, che è ciò che questo problema richiede. l'unica eccezione che ho visto finora è "diff", che non è utile qui.
Grazie.
dati del campione:
pd.DataFrame({
'Store': {0: 1, 1: 1, 2: 1, 3: 1, 4: 1},
'Customers': {0: 668, 1: 578, 2: 619, 3: 635, 4: 785},
'Date': {
0: pd.Timestamp('2013-01-02 00:00:00'),
1: pd.Timestamp('2013-01-03 00:00:00'),
2: pd.Timestamp('2013-01-04 00:00:00'),
3: pd.Timestamp('2013-01-05 00:00:00'),
4: pd.Timestamp('2013-01-07 00:00:00')
}
})
codice che funziona, ma è incredibilmente lento:
import pandas as pd
import numpy as np
data = pd.read_csv("Rossman - no of cust/dataset.csv")
data.Date = pd.to_datetime(data.Date)
data.Customers = data.Customers.astype(int)
for index, row in data.iterrows():
d = row["Date"]
store = row["Store"]
time_condition = (d - data["Date"]<np.timedelta64(60, 'D')) & (d > data["Date"])
sub_df = data.loc[ time_condition & (data["Store"] == store), :]
data.loc[ (data["Date"]==d) & (data["Store"] == store), "Lagged No customers"] = sub_df["Customers"].sum()
data.loc[ (data["Date"]==d) & (data["Store"] == store), "No of days"] = len(sub_df["Customers"])
if len(sub_df["Customers"]) > 0:
data.loc[ (data["Date"]==d) & (data["Store"] == store), "Av No of customers"] = int(sub_df["Customers"].sum()/len(sub_df["Customers"]))
Perché si prende le prime 100 righe di 'data'? ('data [: 100]') –
@Alexander 'time_condition' è solo una maschera che seleziona la finestra temporale corretta, che viene successivamente utilizzata per creare sub_df; @David ZI prende 100 righe per non passare la notte in attesa dell'output, ma l'obiettivo è di avere l'output per l'intero set di dati –
In questo caso penso che sia meglio lasciare il '[: 100]' del codice di esempio in la tua domanda. Dopotutto, il tuo codice di esempio dovrebbe illustrare il problema che stai riscontrando - in questo caso, essere troppo lento. Non è un grosso problema, ma se ti ritrovi a modificare di nuovo per qualche altro motivo, potresti anche prenderlo in considerazione. –