Получить дата начала недели (понедельник) из столбца даты в Python (pandas)?

Я видел много сообщений о том, как вы можете сделать это со строкой даты, но я пытаюсь что-то для столбца dataframe и пока не повезло. Мой текущий метод: получить будний день из "myday", а затем смещение, чтобы получить понедельник.

df['myday'] is column of dates. 
mydays = pd.DatetimeIndex(df['myday']).weekday
df['week_start'] = pd.DatetimeIndex(df['myday']) - pd.DateOffset(days=mydays)

но я вам TypeError: неподдерживаемый тип для компонента timedelta days: numpy.ndarray

Как я могу получить дату начала недели из столбца df?

4 ответов


это не удается, потому что pd.DateOffset ожидает одно целое число в качестве параметра (и вы подаете ему массив). Можно использовать DateOffset только для изменения столбца даты с тем же смещением.

попробуйте это :

import datetime as dt
# Change 'myday' to contains dates as datetime objects
df['myday'] = pd.to_datetime(df['myday'])  
# 'daysoffset' will container the weekday, as integers
df['daysoffset'] = df['myday'].apply(lambda x: x.weekday())
# We apply, row by row (axis=1) a timedelta operation
df['week_start'] = df.apply(lambda x: x['myday'] - dt.TimeDelta(days=x['mydays']), axis=1)

Я на самом деле не тестировал этот код (не было образцов данных), но это должно работать для того, что вы описали.

тем не менее, вы можете посмотреть на панды.Resample, который может обеспечить лучшее решение - в зависимости от именно то, что вы ищете.


другой вариант:

df['week_start'] = df['myday'].dt.to_period('W').apply(lambda r: r.start_time)

это установит 'week_start' в первый понедельник до времени в 'myday'.


хотя оба вышеперечисленных решения работают, я стараюсь держаться подальше от использования apply в Pandas, потому что обычно это довольно медленно по сравнению с методами на основе массива. Чтобы избежать этого, мы можем изменить метод на основе буднего дня и просто указать день недели как numpy timedelta64[D].

df['myday'] - df['myday'].dt.weekday.astype('timedelta64[D]')

используя мои тестовые данные с 60,000 датами, я получил следующие разы, используя два других предложенных ответа и кастинг на основе метод.

%timeit df.apply(lambda x: x['myday'] - datetime.timedelta(days=x['myday'].weekday()), axis=1)
>>> 1 loop, best of 3: 7.43 s per loop
%timeit df['myday'].dt.to_period('W').apply(lambda r: r.start_time)
>>> 1 loop, best of 3: 2.38 s per loop
%timeit df['myday'] - df['myday'].dt.weekday.astype('timedelta64[D]')
>>> 100 loops, best of 3: 12.3 ms per loop

или почти в 200 раз быстрее в моем наборе данных.


(просто добавив к n8yoder'ы ответ)

используя .astype('timedelta64[D]') Кажется мне не очень читаемым - нашел альтернативу, используя только функциональность pandas:

df['myday'] - pd.to_timedelta(arg=df['myday'].dt.weekday, unit='D')