Pertahankan hanya bagian tanggal saat menggunakan panda.to_datetime

201

Saya menggunakan pandas.to_datetimeuntuk menguraikan tanggal dalam data saya. Panda secara default mewakili tanggal dengan datetime64[ns]meskipun tanggal semua hanya harian. Saya bertanya-tanya apakah ada cara yang elegan / pintar untuk mengubah tanggal menjadi datetime.dateatau datetime64[D]sehingga, ketika saya menulis data ke CSV, tanggal tidak ditambahkan 00:00:00. Saya tahu saya bisa mengonversi tipe secara manual elemen demi elemen:

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

Tapi ini sangat lambat karena saya memiliki banyak baris dan itu semacam mengalahkan tujuan penggunaan pandas.to_datetime. Apakah ada cara untuk mengonversi dtypeseluruh kolom sekaligus? Atau sebagai alternatif, apakah pandas.to_datetimemendukung spesifikasi presisi sehingga saya dapat menghilangkan bagian waktu saat bekerja dengan data harian?

jpp
sumber
2
Saya tidak tahu cara yang baik, tetapi df.dates.apply(lambda x: x.date()) harus setidaknya sedikit lebih cepat. lihat juga github.com/pydata/pandas/issues/2583
root
1
Saya akan menganggap kedua pertanyaan ini berbeda. Kemungkinan duplikat yang Anda rujuk bertujuan untuk membagi bagian tanggal dan bagian waktu dari kolom datetime. Pertanyaan ini dimotivasi dengan mengubah seluruh kolom sekaligus. Bayangkan Anda memiliki kerangka data dengan 20 kolom yang mewakili tanggal. Anda tidak ingin menentukan kolom mana yang akan dituliskan ke csv, seperti yang disarankan dalam pertanyaan lain.
1
Ini tidak didukung saat ini (@root menunjuk ke peningkatan yang mungkin), apa tujuan melakukan ini, ketika menulis ke csv?
Jeff
3
Nah, seringkali kita harus menulis data ke file csv untuk dibaca oleh program lain. 00:00:00 yang berlebihan hanya membuat lebih sulit secara umum untuk diproses, terutama ketika saya bekerja dengan data murni setiap hari.

Jawaban:

286

Karena versi 0.15.0ini sekarang dapat dengan mudah dilakukan menggunakan .dtuntuk mengakses hanya komponen tanggal:

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

Di atas mengembalikan datetime.datedtype, jika Anda ingin memiliki datetime64maka Anda dapat hanya normalizekomponen waktu hingga tengah malam sehingga menetapkan semua nilai menjadi 00:00:00:

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

Ini membuat dtype sebagai datetime64tetapi layar hanya menunjukkan datenilai.

EdChum
sumber
33

Solusi sederhana:

df['date_only'] = df['date_time_column'].dt.date
Gil Baggio
sumber
Hanya peringatan, ini mengubah jenis ke objek. Jadi, Anda perlu mengetikkan ('datetime64') untuk menjaga konsistensi.
misantroop
25

Sementara saya meningkatkan jawaban EdChum, yang merupakan jawaban paling langsung untuk pertanyaan yang diajukan OP, itu tidak benar-benar menyelesaikan masalah kinerja (masih bergantung pada datetimeobjek python , dan karenanya setiap operasi pada mereka tidak akan di vectorisasi - yaitu, itu akan lambat).

Alternatif berkinerja lebih baik adalah menggunakan df['dates'].dt.floor('d'). Sebenarnya, itu tidak "tetap hanya bagian tanggal", karena hanya mengatur waktu 00:00:00. Tapi itu berfungsi seperti yang diinginkan oleh OP ketika, misalnya:

  • mencetak ke layar
  • menyimpan ke csv
  • menggunakan kolom untuk groupby

... dan itu jauh lebih efisien, karena operasi ini vektor.

EDIT: pada kenyataannya, jawaban OP lebih suka mungkin "versi terbaru dari pandasyang tidak menulis waktu untuk csv jika 00:00:00untuk semua pengamatan".

Pietro Battiston
sumber
Sayangnya to_jsonmasih menulis penuh 00:00:00.
IanS
@Apakah maksud Anda saat menggunakan date_format='iso'?! Secara default, ini hanya menghasilkan detik sejak zaman.
Pietro Battiston
Ya, itulah yang saya maksud.
IanS
Ini lebih cepat daripada dt.normalize()seri lebih lama dari beberapa ratus elemen.
C8H10N4O2
16

Panda DatetimeIndexdan Seriesmemiliki metode yang disebut normalizeyang melakukan apa yang Anda inginkan.

Anda dapat membaca lebih lanjut tentang hal ini di jawaban ini .

Dapat digunakan sebagai ser.dt.normalize()

Saya tahu
sumber
15

Pandas v0.13 +: Gunakan to_csvdengan date_formatparameter

Hindari, jika mungkin, mengubah datetime64[ns]seri Anda menjadi objectserangkaian datetime.dateobjek dtype . Yang terakhir, sering dibangun menggunakan pd.Series.dt.date, disimpan sebagai array pointer dan tidak efisien relatif terhadap seri berbasis NumPy murni.

Karena kekhawatiran Anda adalah format saat menulis ke CSV , cukup gunakan date_formatparameter to_csv. Sebagai contoh:

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

Lihat arahan Pythonstrftime untuk memformat konvensi.

jpp
sumber
8

Ini adalah cara sederhana untuk mengekstrak tanggal:

import pandas as pd

d='2015-01-08 22:44:09' 
date=pd.to_datetime(d).date()
print(date)
Mani Abi Anand
sumber
OP sudah menggunakan metode .date () dalam pertanyaan mereka, jadi solusi ini tidak menjawab pertanyaan mereka, tapi saya merasa berguna untuk melihat contoh sederhana menggunakan metode date () hanya sebagai referensi.
Nic Scozzaro
5

Konversi ke datetime64[D]:

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

Meskipun menugaskan ulang itu ke col DataFrame akan mengembalikannya kembali ke [ns].

Jika Anda ingin yang sebenarnya 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)])
Dale Jung
sumber
3
Jika Anda menggunakan astype ('M8 [D]'), ia mengubah nilai yang hilang menjadi tanggal asal, 1970-1-1. Mungkin lebih baik menggunakan pandas.to_datetime () saat ini.
Stewbaca
1
Catatan untuk siapa saja yang secara rutin memasukkan modul datetime dt, snipet jawaban ini akan menimpa modul itu! @ Dale-Jung, mungkin dapat mengubah jalur ke sesuatu seperti dt_index
yeliabsalohcin
Saya juga menemukan masalah di mana saat berikutnya saya mencoba dan menambahkan baris baru melalui df.loc[date]metode ini, indeks kembali ke stempel waktu, yang berarti perbandingan selanjutnya tidak lagi berfungsi
yeliabsalohcin
3

Hanya memberikan jawaban yang lebih terkini jika seseorang melihat posting lama ini.

Menambahkan "utc = False" saat mengonversi ke datetime akan menghapus komponen zona waktu dan hanya menyimpan tanggal dalam tipe data datetime64 [ns].

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

Anda akan dapat menyimpannya di excel tanpa mendapatkan kesalahan "ValueError: Excel tidak mendukung datetimes dengan zona waktu. Harap pastikan bahwa datet Zone tidak menyadari zona waktu sebelum menulis ke Excel."

masukkan deskripsi gambar di sini

Katekarin
sumber
Ini karena beberapa alasan gagal setelah Anda menerapkan fungsi agregat apa pun dengan kolom.
RaphX
0

Saya ingin dapat mengubah jenis kumpulan kolom dalam bingkai data dan kemudian menghapus waktu menjaga hari. round (), floor (), ceil () semuanya berfungsi

df[date_columns] = df[date_columns].apply(pd.to_datetime)
df[date_columns] = df[date_columns].apply(lambda t: t.dt.floor('d'))
Climbs_lika_Spyder
sumber