Zachowaj tylko datę podczas korzystania z pandas.to_datetime


201

Używam pandas.to_datetimedo analizowania dat w moich danych. Pandy domyślnie reprezentują daty, datetime64[ns]mimo że wszystkie są tylko codziennie. Zastanawiam się, czy istnieje elegancki / sprytny sposób na konwersję dat, datetime.dateczy też datetime64[D]tak, że kiedy piszę dane do CSV, daty nie są dołączane 00:00:00. Wiem, że mogę ręcznie przekonwertować typ element po elemencie:

[dt.to_datetime().date() for dt in df.dates]

Ale to jest naprawdę wolne, ponieważ mam wiele wierszy i to w pewnym sensie nie pozwala na użycie pandas.to_datetime. Czy istnieje sposób na konwersję dtypecałej kolumny jednocześnie? Czy też pandas.to_datetimeobsługuje precyzyjne specyfikacje, dzięki którym mogę pozbyć się części czasu podczas pracy z codziennymi danymi?


2
Nie znam dobrego sposobu, ale df.dates.apply(lambda x: x.date()) powinienem być co najmniej trochę szybszy. spójrz także na github.com/pydata/pandas/issues/2583
— root


1
Te dwa pytania uznałbym za różne. Możliwy duplikat, do którego się odwołujesz, ma na celu podzielenie części daty i części godziny z kolumny daty i godziny. To pytanie jest motywowane przez konwersję całej kolumny na raz. Wyobraź sobie, że masz ramkę danych z 20 kolumnami reprezentującymi daty. Nie chciałbyś określać, które kolumny pisać do csv, jak sugerowano w drugim pytaniu.

1
Obecnie nie jest to obsługiwane (@root wskazuje na możliwe ulepszenie), jaki jest cel tego, pisząc do csv?
— Jeff

3
Cóż, często musimy zapisywać dane w plikach csv, aby mogły je odczytać inne programy. Nadmiarowa 00:00:00 sprawia, że ​​ogólnie trudniej jest ją przetwarzać, szczególnie gdy pracuję z danymi wyłącznie codziennymi.

Odpowiedzi:


285

Od wersji 0.15.0można to teraz łatwo zrobić za pomocą .dtdostępu do komponentu daty:

df['just_date'] = df['dates'].dt.date

Powyższe zwraca datetime.datetyp dtype, jeśli chcesz go mieć datetime64, możesz tylko normalizekomponent czasu do północy, aby ustawić wszystkie wartości na 00:00:00:

df['normalised_date'] = df['dates'].dt.normalize()

To zachowuje typ, datetime64ale wyświetlacz pokazuje tylko datewartość.


33

Proste rozwiązanie:

df['date_only'] = df['date_time_column'].dt.date

Tylko ostrzeżenie, to zmienia typ na obiekt. Aby zachować spójność, trzeba by astype („datetime64”).
— misantroop

25

Chociaż głosowałem za odpowiedzią EdChum, która jest najbardziej bezpośrednią odpowiedzią na postawione przez OP pytanie, to tak naprawdę nie rozwiązuje problemu wydajności (nadal opiera się na datetimeobiektach python , a zatem wszelkie operacje na nich nie będą wektoryzowane - to znaczy będzie wolny).

Lepszą skutecznością jest użycie df['dates'].dt.floor('d'). Ściśle mówiąc, nie „zachowuje tylko daty”, ponieważ po prostu ustawia czas 00:00:00. Ale działa zgodnie z oczekiwaniami PO, gdy na przykład:

  • drukowanie na ekran
  • zapisywanie do csv
  • za pomocą kolumny do groupby

... i jest znacznie wydajniejszy, ponieważ operacja jest wektoryzowana.

EDIT: w rzeczywistości, odpowiedź PO byłaby korzystna jest prawdopodobnie „Nowsze wersje pandasmają nie napisać czasu do CSV, jeśli jest 00:00:00dla wszystkich obserwacji”.


Niestety to_jsonnadal pisze pełny 00:00:00.
— IanS

@IanS masz na myśli, kiedy używasz date_format='iso'? Domyślnie wyświetla tylko sekundy od epoki.
— Pietro Battiston

Tak właśnie miałem na myśli.
— IanS

Jest to szybsze niż dt.normalize()w seriach dłuższych niż kilkaset elementów.
— C8H10N4O2

16

Pandy DatetimeIndexi Serieswywołać metodę, normalizektóra robi dokładnie to, co chcesz.

Możesz przeczytać więcej na ten temat w tej odpowiedzi .

Może być używany jako ser.dt.normalize()


15

Pandas v0.13 +: Użyj to_csvz date_formatparametrem

W miarę możliwości unikaj przekształcania datetime64[ns]serii w objectserię datetime.dateobiektów typu dtype . Ten ostatni, często skonstruowany przy użyciu pd.Series.dt.date, jest przechowywany jako tablica wskaźników i jest nieefektywny w stosunku do serii opartej wyłącznie na NumPy.

Ponieważ Twoja obawa dotyczy formatu podczas pisania do pliku CSV , wystarczy użyć date_formatparametru to_csv. Na przykład:

df.to_csv(filename, date_format='%Y-%m-%d')

Zobacz dyrektywy Pythona strftimedotyczące konwencji formatowania.


8

Jest to prosty sposób na wyodrębnienie daty:

import pandas as pd

d='2015-01-08 22:44:09' 
date=pd.to_datetime(d).date()
print(date)

OP używa już metody .date () w swoim pytaniu, więc to rozwiązanie nie odpowiada na ich pytanie, ale uznałem za użyteczny prosty przykład użycia metody date () jako odniesienia.
— Nic Scozzaro

5

Konwertowanie na datetime64[D]:

df.dates.values.astype('M8[D]')

Chociaż ponowne przypisanie tego do kolumny DataFrame spowoduje przywrócenie go z powrotem do [ns].

Jeśli chcesz faktycznie datetime.date:

dt = pd.DatetimeIndex(df.dates)
dates = np.array([datetime.date(*date_tuple) for date_tuple in zip(dt.year, dt.month, dt.day)])

3
Jeśli używasz astype („M8 [D]”), przekształca brakujące wartości w datę początkową, 1970-1-1. Prawdopodobnie lepiej jest teraz po prostu używać pandas.to_datetime ().
— Stewbaca,

1
Uwaga dla każdego, kto rutynowo dtdołącza moduł datetime, ponieważ ten fragment odpowiedzi zastąpi ten moduł! @ Dale-Jung, być może może zmienić linię na coś takiego jak dt_index
— yeliabsalohcin

Znajduję również problem, w którym przy następnej próbie dodania nowego wiersza za pomocą df.loc[date]metody indeks wraca do znacznika czasu, co oznacza, że ​​kolejne porównania już nie działają
— yeliabsalohcin

3

Po prostu udzielam bardziej aktualnej odpowiedzi na wypadek, gdyby ktoś zobaczył ten stary post.

Dodanie „utc = False” podczas konwersji na datetime spowoduje usunięcie komponentu strefy czasowej i zachowanie tylko daty w typie danych datetime64 [ns].

pd.to_datetime(df['Date'], utc=False)

Będzie można go zapisać w programie Excel bez wyświetlania błędu „Błąd wartości: program Excel nie obsługuje czasów danych w strefach czasowych. Przed zapisaniem w programie Excel upewnij się, że czasy danych nie są znane.

wprowadź opis zdjęcia tutaj


To z jakiegoś powodu kończy się niepowodzeniem po zastosowaniu dowolnej funkcji agregującej w kolumnie.
— RaphX

0

Chciałem móc zmienić typ zestawu kolumn w ramce danych, a następnie usunąć czas, utrzymując dzień. round (), floor (), ceil () wszystkie prace

df[date_columns] = df[date_columns].apply(pd.to_datetime)
df[date_columns] = df[date_columns].apply(lambda t: t.dt.floor('d'))
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.