TimedeltaIndex
es rappresentano intervalli di tempo fissi. Possono essere aggiunti ai timestamp di Pandas per incrementarli di importi fissi. Il loro comportamento non dipende mai dal fatto che Timestamp sia o meno un giorno lavorativo. TimedeltaIndex non è mai al corrente del giorno lavorativo.
Poiché l'obiettivo finale è contare il numero di giorni tra un DatetimeIndex e un Timestamp, guarderei in un'altra direzione rispetto alla conversione in TimedeltaIndex.
Purtroppo, i calcoli di data sono piuttosto complicate, e un certo numero di strutture di dati sono sorti per trattare con loro - Python datetime.dates
, datetime.datetime
s, Panda Timestamps
, NumPy datetime64
s.
Ognuno di loro ha i suoi punti di forza, ma nessuno di loro è buono a tutti gli effetti. Per sfruttare i loro punti di forza, è talvolta necessario convertire tra questi tipi.
Per utilizzare np.busday_count
è necessario convertire il DatetimeIndex e timestamp per un certo tipo np.busday_count
capisce. Quello che chiami kludginess è il codice richiesto per convertire i tipi. Non c'è modo di supporre che vogliamo usare np.busday_count
- e non conosco nessuno strumento migliore per questo lavoro di np.busday_count
.
Quindi, anche se non credo che ci sia un modo più succinto contare giorni lavorativi che rispetto al metodo che proponete, c'è un modo molto più performante: Converti in datetime64[D]
's invece di Python datetime.date
oggetti:
import pandas as pd
import numpy as np
drg = pd.date_range('2000-07-31', '2015-08-05', freq='B')
timestamp = pd.Timestamp('2015-08-05', 'B')
def using_astype(drg, timestamp):
A = drg.values.astype('<M8[D]')
B = timestamp.asm8.astype('<M8[D]')
return np.busday_count(A, B)
def using_datetimes(drg, timestamp):
A = [d.date() for d in drg]
B = pd.Timestamp('2015-08-05', 'B').date()
return np.busday_count(A, B)
Questo è più di 100 volte più veloce per l'esempio di cui sopra (dove len(drg)
è vicino a 4000):
In [88]: %timeit using_astype(drg, timestamp)
10000 loops, best of 3: 95.4 µs per loop
In [89]: %timeit using_datetimes(drg, timestamp)
100 loops, best of 3: 10.3 ms per loop
np.busday_count
converte il proprio input in datetime64[D]
s in ogni caso, quindi evitare questa conversione aggiuntiva da e verso datetime.date
s è molto più efficiente.
Grazie, anche se la mia applicazione non è molto performante, la mia soluzione era decisamente abbastanza lenta da infastidirmi, quindi questa accelerazione è molto apprezzata. Buono a sapersi su cosa sta succedendo sotto il cofano. – mgilbert
Sono un po 'confuso qui. Se stiamo solo cercando di contare il numero di giorni lavorativi, non 'pd.date_range (start, end, freq = 'B'). Size' ce lo danno immediatamente? Non c'è bisogno di usare Numpy affatto. –
@JohnTyree: il problema è trovare il numero di giorni lavorativi tra un DatetimeIndex e un Timestamp. 'pd.date_range (start, end, freq = 'B'). size' trova il numero di giorni lavorativi tra due date. Dovresti chiamarlo in un ciclo per ogni giorno nel DatetimeIndex. Se hai tempo '[pd.date_range (drg [i], timestamp, freq = 'B'). Size - 1 per i in range (len (drg))]" troverai che è estremamente lento. – unutbu