2017-01-28 21 views
5

Pytanie:wektoryzowane sposób do kwerendy datę i cenę danych

Przegląd:

ja szukam wektoryzowane sposobem uzyskania pierwszego dnia, pewien warunek jest postrzegana. Warunek znajduje się, gdy cena w dfDays wynosi > cenę docelową określoną w dfWeeks.target. Ten warunek musi zostać osiągnięty po dacie ustawienia celu.

Czy istnieje sposób przeprowadzenia poniższej analizy szeregów czasowych z apply lub podobnym, w sposób wektorowy w języku Pandy?


danych:

Generowanie freq='D' Test dataframe

np.random.seed(seed=1) 
rng = pd.date_range('1/1/2000', '2000-07-31',freq='D') 
weeks = np.random.uniform(low=1.03, high=3, size=(len(rng),)) 
ts2 = pd.Series(weeks 
       ,index=rng) 
dfDays = pd.DataFrame({'price':ts2}) 

Teraz utworzyć resamplingowi freq='1W-Mon' dataframe

dfWeeks = dfDays.resample('1W-Mon').first() 
dfWeeks['target'] = (dfWeeks['price'] + .5).round(2) 

Zastosowanie reindex wyrównać indeks zarówno d f:

dfWeeks = dfWeeks.reindex(dfDays.index) 

Więc dfWeeks jest dataframe zawierający wartości docelowych użyjemy

dfWeeks.dropna().head() 

       price target 
2000-01-03 1.851533 2.35 
2000-01-10 1.625595 2.13 
2000-01-17 1.855813 2.36 
2000-01-24 2.130619 2.63 
2000-01-31 2.756487 3.26 

Jeśli skupimy się na pierwszej tarczy z dfWeeks

match = dfDays[dfDays.price >= dfWeeks.target.loc['2000-01-03']] 

Pierwszy mecz jest w przeszłość jest niepoprawna, więc wpis 2000-01-12 jest pierwszym prawidłowym dopasowaniem:

match.head() 

      price 
2000-01-02 2.449039 
2000-01-12 2.379882 
2000-01-14 2.759891 
2000-01-16 2.350821 
2000-01-21 2.607467 

enter image description here

Czy istnieje sposób to zrobić z apply lub podobny do target wpisów w dfWeeks w wektoryzowane sposób?

sygnał wyjściowy:

   price target target_hit 
2000-01-03 1.851533 2.35 2000-01-12 
2000-01-10 1.625595 2.13 2000-01-12 
2000-01-17 1.855813 2.36 2000-01-21 
2000-01-24 2.130619 2.63 2000-01-25 
2000-01-31 2.756487 3.26 nan 
+0

Nie rozumiem logiki - Skąd masz '' target' i kolumny target_hit' w żądanych danych ustawić – MaxU

+0

wygląda mi jak [ „XY problem”] (http: // meta. stackexchange.com/a/66378/348814), kiedy koncentrujesz się na tym konkretnym rozwiązaniu, podczas gdy mogą być lepsze. Właśnie dlatego próbuję zrozumieć, co chcesz osiągnąć. – MaxU

+1

@Maxu, zaktualizowałem post z przeglądem tego, co próbuję osiągnąć. – ade1e

Odpowiedz

5

pandas

def find_match(x): 
    match = dfDays.query('index > @x.name & price >= @x.target') 
    if not match.empty: 
     return match.index[0] 

dfWeeks.assign(target_hit=dfWeeks.apply(find_match, 1)) 

numpy

timing = dfWeeks.index.values[:, None] < dfDays.index.values 
target_hit = dfWeeks.target.values[:, None] <= dfDays.price.values 
matches = timing & target_hit 
got_match = matches.any(1) 
first = matches.argmax(1)[got_match] 

dfWeeks.loc[got_match, 'target_hit'] = dfDays.index.values[first] 
dfWeeks 

zarówno wydajność

   price target target_hit 
2000-01-03 1.851533 2.35 2000-01-12 
2000-01-10 1.625595 2.13 2000-01-12 
2000-01-17 1.855813 2.36 2000-01-21 
2000-01-24 2.130619 2.63 2000-01-25 
2000-01-31 2.756487 3.26  NaT 
2000-02-07 1.859582 2.36 2000-02-09 
2000-02-14 1.066028 1.57 2000-02-15 
2000-02-21 1.912350 2.41 2000-03-09 
2000-02-28 1.446907 1.95 2000-02-29 
2000-03-06 2.408524 2.91 2000-03-28 
2000-03-13 2.337675 2.84 2000-03-17 
2000-03-20 2.620561 3.12  NaT 
2000-03-27 2.770113 3.27  NaT 
2000-04-03 2.930735 3.43  NaT 
2000-04-10 1.834030 2.33 2000-04-12 
2000-04-17 2.068304 2.57 2000-04-19 
2000-04-24 2.391067 2.89 2000-05-11 
2000-05-01 2.518262 3.02  NaT 
2000-05-08 1.085764 1.59 2000-05-10 
2000-05-15 1.579992 2.08 2000-05-16 
2000-05-22 2.619997 3.12  NaT 
2000-05-29 1.269047 1.77 2000-05-31 
2000-06-05 1.171789 1.67 2000-06-06 
2000-06-12 2.175277 2.68 2000-06-20 
2000-06-19 1.338879 1.84 2000-06-20 
2000-06-26 2.977574 3.48  NaT 
2000-07-03 1.160680 1.66 2000-07-04 
2000-07-10 2.615366 3.12  NaT 
2000-07-17 2.478080 2.98  NaT 
2000-07-24 2.899562 3.40  NaT 
2000-07-31 2.220492 2.72  NaT 
+0

Miałem zamiar zostawić to pytanie na kilka dni, a następnie poprosić o pomoc, jeśli brak odpowiedzi @piRSquared. Tak szczęśliwy, że masz twoją pomoc, Sir! – ade1e

+1

Zaktualizowano również podejście "numpy". Cieszę się, że mogę pomóc – piRSquared

+1

Rozwiązanie "numpy" jest bardzo łatwe do wdrożenia na moich prawdziwych danych. Wspaniały! – ade1e

1

prostu dodaje się razem do zapytania. Numpy naprawdę świeci tutaj.

Czy ktoś mógłby potwierdzić wyniki, testując to samo na swoim komputerze.

import pandas as pd 
import numpy as np 

np.random.seed(seed=1) 
rng = pd.date_range('1/1/2000', '2000-07-31',freq='D') 
weeks = np.random.uniform(low=1.03, high=3, size=(len(rng),)) 
ts2 = pd.Series(weeks 
       ,index=rng) 
dfDays = pd.DataFrame({'price':ts2}) 
dfWeeks = dfDays.resample('1W-Mon').first() 
dfWeeks['target'] = (dfWeeks['price'] + .5).round(2) 

pandy

%%timeit 
def find_match(x): 
    match = dfDays.query('index > @x.name & price >= @x.target') 
    if not match.empty: 
     return match.index[0] 

dfWeeks.assign(target_hit=dfWeeks.apply(find_match, 1)) 

10 loops, best of 3: 66 ms per loop

numpy

%timeit 
timing = dfWeeks.index.values[:, None] < dfDays.index.values 
target_hit = dfWeeks.target.values[:, None] <= dfDays.price.values 
matches = timing & target_hit 
got_match = matches.any(1) 
first = matches.argmax(1)[got_match] 

dfWeeks.loc[got_match, 'target_hit'] = dfDays.index.values[first] 
dfWeeks 

Najwolniejszym run trwało 4.10 razy dłużej niż najszybszy. Może to być oznacza, że ​​wynik pośredni jest buforowany. 1000 loops, best of 3: 999 µs per loop