Próbuję znaleźć skuteczny sposób generowania liczby lub kwot toczenia w pandach z uwzględnieniem grupy i zakresu dat. W końcu chcę móc dodać warunki, tj. oceniając pole "typ", ale jeszcze go nie ma. Napisałem coś, aby wykonać tę pracę, ale uważam, że może istnieć bardziej bezpośredni sposób osiągnięcia pożądanego rezultatu.Wydajna agregacja toczenia pand w zakresie dat według grup - Python 2.7 Windows - Pandy 0.19.2
Moja ramka danych o pandach wygląda obecnie tak, a żądane dane wyjściowe są umieszczane w ostatniej kolumnie "rolling_sales_180".
name date amount rolling_sales_180
0 David 2015-01-01 100 100.0
1 David 2015-01-05 500 600.0
2 David 2015-05-30 50 650.0
3 David 2015-07-25 50 100.0
4 Ryan 2014-01-04 100 100.0
5 Ryan 2015-01-19 500 600.0
6 Ryan 2016-03-31 50 650.0
7 Joe 2015-07-01 100 100.0
8 Joe 2015-09-09 500 500.0
9 Joe 2015-10-15 50 50.0
Moje obecne rozwiązanie i środowisko można pobrać poniżej. Modelowałem swoje rozwiązanie z tego R Q & A in stackoverflow. Efficient way to perform running total in the last 365 day window
import pandas as pd
import numpy as np
def trans_date_to_dist_matrix(date_col): # used to create a distance matrix
x = date_col.tolist()
y = date_col.tolist()
data = []
for i in x:
tmp = []
for j in y:
tmp.append(abs((i - j).days))
data.append(tmp)
del tmp
return pd.DataFrame(data=data, index=date_col.values, columns=date_col.values)
def lower_tri(x_col, date_col, win): # x_col = column user wants a rolling sum of ,date_col = dates, win = time window
dm = trans_date_to_dist_matrix(date_col=date_col) # dm = distance matrix
dm = dm.where(dm <= win) # find all elements of the distance matrix that are less than window(time)
lt = dm.where(np.tril(np.ones(dm.shape)).astype(np.bool)) # lt = lower tri of distance matrix so we get only future dates
lt[lt >= 0.0] = 1.0 # cleans up our lower tri so that we can sum events that happen on the day we are evaluating
lt = lt.fillna(0) # replaces NaN with 0's for multiplication
return pd.DataFrame(x_col.values * lt.values).sum(axis=1).tolist()
def flatten(x):
try:
n = [v for sl in x for v in sl]
return [v for sl in n for v in sl]
except:
return [v for sl in x for v in sl]
data = [
['David', '1/1/2015', 100], ['David', '1/5/2015', 500], ['David', '5/30/2015', 50], ['David', '7/25/2015', 50],
['Ryan', '1/4/2014', 100], ['Ryan', '1/19/2015', 500], ['Ryan', '3/31/2016', 50],
['Joe', '7/1/2015', 100], ['Joe', '9/9/2015', 500], ['Joe', '10/15/2015', 50]
]
list_of_vals = []
dates_df = pd.DataFrame(data=data, columns=['name', 'date', 'amount'], index=None)
dates_df['date'] = pd.to_datetime(dates_df['date'])
list_of_vals.append(dates_df.groupby('name', as_index=False).apply(
lambda x: lower_tri(x_col=x.amount, date_col=x.date, win=180)))
new_data = flatten(list_of_vals)
dates_df['rolling_sales_180'] = new_data
print dates_df
Twój czas i opinie są mile widziane.
Czy jesteś pewien, próbka wynik dla "rolling_sales_180" jest poprawny? Ta kolumna ma być 180 ruchomą sumą, prawda? Wszystkie daty Ryana są ponad rok od siebie, ale wciąż są podsumowywane? I wszystkie terminy dla Joe są w ciągu 180 dni i nie są sumowane? Czy w jakiś sposób zmieniłeś dwa? – root
@root - Mogłem nieprawidłowo przetransponować - przepraszam. – rs311
Bez obaw, upewniając się, że rozumiem problem. – root