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

Я видел много постов о том, как вы можете сделать это с помощью строки даты, но я пытаюсь что-то сделать для столбца данных, и пока мне не повезло. Мой текущий метод: получить день недели от "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)

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

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

Другая альтернатива:

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

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

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

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

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

%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]') кажется, не так легко читается - нашел альтернативу, используя только функциональность панд:

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

# Convert column to pandas datetime equivalent
df['myday'] = pd.to_datetime(df['myday']) 

# Create function to calculate Start Week date
week_start_date = lambda date: date - timedelta(days=date.weekday())

# Apply above function on DataFrame column
df['week_start_date'] = df['myday'].apply(week_start_date)
Другие вопросы по тегам