2012-12-09 9 views
13

mam pandas.DatetimeIndex, np .:Jak zaokrąglić Pandy "DatetimeIndex"?

pd.date_range('2012-1-1 02:03:04.000',periods=3,freq='1ms') 
>>> [2012-01-01 02:03:04, ..., 2012-01-01 02:03:04.002000] 

Chciałbym zaokrąglić daty (Timestamp ów) najbliższej sekundy. Jak mogę to zrobić? Oczekiwany wynik jest podobny do:

[2012-01-01 02:03:04.000000, ..., 2012-01-01 02:03:04.000000] 

Czy to możliwe, aby osiągnąć ten cel przez zaokrąglania Numpy datetime64[ns] do sekundach bez zmiany dtype[ns]?

np.array(['2012-01-02 00:00:00.001'],dtype='datetime64[ns]') 
+0

@hayden, zobacz moją edycję. Chcę tylko zaokrąglić do najbliższej sekundy. – Yariv

+0

'date_range' domyślnie przyjmuje częstotliwość dzienną, zakładam że miałeś' pd.date_range ('2012-1-1 00: 00.000', okres = 2, freq = 'S') ' –

+0

@MattiJohn, zobacz moją poprawkę. Miałem na myśli * ten sam * sekundę do powtórzenia. – Yariv

Odpowiedz

16

Aktualizacja: jeśli robisz to na kolumnę DatetimeIndex/datetime64 lepszym sposobem jest użycie np.round bezpośrednio raczej niż poprzez zastosowanie/Mapa:

np.round(dtindex_or_datetime_col.astype(np.int64), -9).astype('datetime64[ns]') 

Old odpowiedź (z pewnego m wyjaśnienie rudy):

Podczas @ odpowiedź Mattiego jest oczywiście poprawny sposób do czynienia z sytuacją, myślałem, że chciałbym dodać odpowiedź jak można zaokrąglić znacznikiem czasu z dokładnością do sekundy:

from pandas.lib import Timestamp 

t1 = Timestamp('2012-1-1 00:00:00') 
t2 = Timestamp('2012-1-1 00:00:00.000333') 

In [4]: t1 
Out[4]: <Timestamp: 2012-01-01 00:00:00> 

In [5]: t2 
Out[5]: <Timestamp: 2012-01-01 00:00:00.000333> 

In [6]: t2.microsecond 
Out[6]: 333 

In [7]: t1.value 
Out[7]: 1325376000000000000L 

In [8]: t2.value 
Out[8]: 1325376000000333000L 

# Alternatively: t2.value - t2.value % 1000000000 
In [9]: long(round(t2.value, -9)) # round milli-, micro- and nano-seconds 
Out[9]: 1325376000000000000L 

In [10]: Timestamp(long(round(t2.value, -9))) 
Out[10]: <Timestamp: 2012-01-01 00:00:00> 

Stąd ci można zastosować to do całego indeksu:

def to_the_second(ts): 
    return Timestamp(long(round(ts.value, -9))) 

dtindex.map(to_the_second) 
+0

Wygląda na to, że '1000000' powinno zostać zastąpione' 1000000000'. – Yariv

+0

Co ważne, chciałbym to zrobić na 'DatetimeIndex'. – Yariv

+0

@ user1579844 masz rację oczywiście! Zapomniałem o milli sekundach ... okrzyki! Poprawiłem to i dodałem jak zastosować to do całego dt_indeksu. –

4

Nie ma sensu w zmianie samego indeksu - skoro można po prostu wygenerować za pomocą date_range z pożądanym parametrem częstotliwości, jak w swoim pytaniu.

Zakładam, że próbujesz zmienić częstotliwość serii czasu, która zawiera dane. W takim przypadku możesz użyć resample (documentation). Na przykład, jeśli masz następujący szereg czasowy:

dt_index = pd.date_range('2012-1-1 00:00.001',periods=3, freq='1ms') 
ts = pd.Series(randn(3), index=dt_index) 


2012-01-01 00:00:00   0.594618 
2012-01-01 00:00:00.001000 0.874552 
2012-01-01 00:00:00.002000 -0.700076 
Freq: L 

Następnie można zmienić częstotliwość na sekundy przy użyciu resample, określając w jaki sposób chcesz agregować wartości (średnia, suma itd.):

ts.resample('S', how='sum') 

2012-01-01 00:00:00 0.594618 
2012-01-01 00:00:01 0.174475 
Freq: S 
+0

To eliminuje niektóre wiersze. Chciałbym tylko * zmienić * wartość indeksu, zaokrąglając ją do najbliższej sekundy. – Yariv

+0

ah, przepraszam, nie zdawałem sobie sprawy, że chciałeś zduplikować wartości. Wygląda na to, że zaktualizowana odpowiedź @ haydena zrobi, co chcesz –

3

na bardziej ogólnym zaokrąglenia, można skorzystać z faktu, że Pandy Timestamp obiekty najczęściej korzystają z biblioteki standardowej datetime.datetime API, w tym metody datetime.datetime.replace().

Tak więc, aby rozwiązać swój problem zaokrąglania mikrosekund, można zrobić:

import datetime 
import pandas as pd 

times = pd.date_range('2012-1-1 02:03:04.499',periods=3,freq='1ms') 
# Add 5e5 microseconds and truncate to simulate rounding 
times_rounded = [(x + datetime.timedelta(microseconds=5e5)).replace(microsecond=0) for x in times] 

from IPython.display import display 
print('Before:') 
display(list(times)) 
print('After:') 
display(list(times_rounded)) 

wyjściowa:

Before: 
[Timestamp('2012-01-01 02:03:04.499000', offset='L'), 
Timestamp('2012-01-01 02:03:04.500000', offset='L'), 
Timestamp('2012-01-01 02:03:04.501000', offset='L')] 
After: 
[Timestamp('2012-01-01 02:03:04', offset='L'), 
Timestamp('2012-01-01 02:03:05', offset='L'), 
Timestamp('2012-01-01 02:03:05', offset='L')] 

można użyć tej samej techniki, aby, na przykład, okrągłe do najbliższego dnia (jak o ile nie interesują Cię sekundy przestępne i podobne):

times = pd.date_range('2012-1-1 08:00:00', periods=3, freq='4H') 
times_rounded = [(x + datetime.timedelta(hours=12)).replace(hour=0, second=0, microsecond=0) for x in times] 

Zainspirowany tym słowem ost: https://stackoverflow.com/a/19718411/1410871

10

round() Metoda została dodana dla DatetimeIndex, Timestamp, TimedeltaIndex i Timedelta w pandach 0.18.0.Teraz możemy wykonać następujące czynności:

In[114]: index = pd.DatetimeIndex([pd.Timestamp('2012-01-01 02:03:04.000'), pd.Timestamp('2012-01-01 02:03:04.002'), pd.Timestamp('20130712 02:03:04.500'), pd.Timestamp('2012-01-01 02:03:04.501')]) 

In[115]: index.values 
Out[115]: 
array(['2012-01-01T02:03:04.000000000', '2012-01-01T02:03:04.002000000', 
     '2013-07-12T02:03:04.500000000', '2012-01-01T02:03:04.501000000'], dtype='datetime64[ns]') 

In[116]: index.round('S') 
Out[116]: 
DatetimeIndex(['2012-01-01 02:03:04', '2012-01-01 02:03:04', 
       '2013-07-12 02:03:04', '2012-01-01 02:03:05'], 
       dtype='datetime64[ns]', freq=None) 

round() akceptuje parametr częstotliwości. Aliasy napisów dla niego są wymienione here.

Powiązane problemy