Сохраняйте только часть даты при использовании pandas.to_datetime

229

Я использую pandas.to_datetimeдля разбора дат в моих данных. Pandas по умолчанию представляет даты, datetime64[ns]хотя все даты только ежедневные. Интересно, есть ли элегантный / умный способ преобразовать даты в datetime.dateили datetime64[D]так, чтобы при записи данных в CSV к датам не добавлялись 00:00:00. Я знаю, что могу преобразовать тип вручную поэлементно:

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

Но это действительно медленно, так как у меня много строк, и это как бы поражает цель использования pandas.to_datetime. Есть ли способ преобразовать dtypeсразу весь столбец? Или, наоборот, pandas.to_datetimeподдерживает ли спецификацию точности, чтобы я мог избавиться от временной части при работе с ежедневными данными?

jpp
источник

Ответы:

327

Начиная с версии, 0.15.0это теперь можно легко сделать, используя .dtтолько компонент даты:

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

Вышеупомянутый возвращает datetime.datedtype, если вы хотите иметь, datetime64тогда вы можете просто normalizeустановить компонент времени на полночь, чтобы он установил все значения на 00:00:00:

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

Это сохраняет dtypeas datetime64, но на дисплее отображается только dateзначение.

EdChum
источник
51

Простое решение:

df['date_only'] = df['date_time_column'].dt.date
Гил Баджо
источник
10
Просто предупреждение, это меняет тип на объект. Таким образом, вам нужно будет ввести Astype ('datetime64'), чтобы сохранить согласованность.
человеконенавистник
26

Хотя я поддержал ответ EdChum, который является наиболее прямым ответом на вопрос, поставленный OP, на самом деле он не решает проблему производительности (он по-прежнему полагается на datetimeобъекты python , и, следовательно, любая операция с ними не будет векторизована, то есть будет медленно).

Более эффективная альтернатива - использовать df['dates'].dt.floor('d'). Строго говоря, он не «сохраняет только часть даты», поскольку просто устанавливает время на 00:00:00. Но он работает так, как того требует OP, например, когда:

  • печать на экране
  • сохранение в CSV
  • используя столбец для groupby

... и это намного эффективнее, поскольку операция векторизована.

EDIT: на самом деле, ответ на ОП - х предпочли бы, вероятно , «последние версии pandasэтого не пишут время в формате CSV , если это 00:00:00для всех наблюдений».

Пьетро Баттистон
источник
К сожалению to_jsonдо сих пор пишет полный 00:00:00.
IanS
@IanS ты имеешь ввиду при использовании date_format='iso'?! По умолчанию он просто выводит секунды с начала эпохи.
Пьетро Баттистон,
Да, это я имел в виду.
IanS
Это быстрее, чем dt.normalize()для серий из нескольких сотен элементов.
C8H10N4O2
19

Pandas v0.13 +: использовать to_csvс date_formatпараметром

По возможности избегайте преобразования вашей datetime64[ns]серии в objectсерию datetime.dateобъектов dtype . Последний, часто создаваемый с использованием pd.Series.dt.date, хранится как массив указателей и неэффективен по сравнению с чистой серией на основе NumPy.

Поскольку вас интересует формат при записи в CSV , просто используйте date_formatпараметр to_csv. Например:

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

См . strftimeПравила форматирования в директивах Python .

jpp
источник
18

Pandas, DatetimeIndexи у Seriesвас есть метод, normalizeкоторый делает именно то, что вы хотите.

Вы можете прочитать об этом больше в этом ответе .

Его можно использовать как ser.dt.normalize()

j08lue
источник
11

Это простой способ извлечь дату:

import pandas as pd

d='2015-01-08 22:44:09' 
date=pd.to_datetime(d).date()
print(date)
Мани Аби Ананд
источник
OP уже использует метод .date () в своем вопросе, поэтому это решение не отвечает на их вопрос, но я счел полезным увидеть простой пример использования метода date () в качестве справки.
Ник Скоццаро,
6

Просто даю более свежий ответ на случай, если кто-то увидит этот старый пост.

Добавление «utc = False» при преобразовании в datetime удалит компонент часового пояса и сохранит только дату в типе данных datetime64 [ns].

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

Вы сможете сохранить его в Excel, не получая сообщения об ошибке «ValueError: Excel не поддерживает дату и время с часовыми поясами. Перед записью в Excel убедитесь, что для даты не указан часовой пояс».

введите описание изображения здесь

Катекарин
источник
1
По какой-то причине это не удается после применения какой-либо агрегатной функции к столбцу.
RaphX,
5

Преобразование в datetime64[D]:

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

Хотя переназначение этого столбцу DataFrame вернет его обратно к [ns].

Если вы хотели актуальные 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
Если вы используете astype ('M8 [D]'), он преобразует отсутствующие значения в дату происхождения 1970-1-1. Наверное, сейчас лучше просто использовать pandas.to_datetime ().
Stewbaca
1
Обратите внимание на всех, кто регулярно включает модуль datetime, поскольку dtэтот фрагмент ответа перезапишет этот модуль! @ Дейл-Юнг, возможно, можно было бы сменить строку на что-то вроде dt_index
yeliabsalohcin 01
Я также нахожу проблему, при которой в следующий раз, когда я пытаюсь добавить новую строку с помощью этого df.loc[date]метода, индекс возвращается к
отметке
2

Я хотел иметь возможность изменить тип набора столбцов во фрейме данных, а затем удалить время, сохраняющее день. round (), floor (), ceil () все работает

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
источник
0

Это сработало для меня с отметкой времени UTC (2020-08-19T09: 12: 57.945888)

for di, i in enumerate(df['YourColumnName']):
    df['YourColumnName'][di] = pd.Timestamp(i)
Пуннеруд
источник