Pandas Timestamp
s и Python datetime.date
s сообщают ISO 8601 номера недели :
import datetime as DT
import pandas as pd
df = pd.DataFrame(['2018-12-28', '2018-12-29', '2018-12-30', '2018-12-31',
'2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04'],
columns=['date'])
df['date'] = pd.to_datetime(df['date'], format='%Y-%m-%d')
df['datenum'] = df['date'].dt.week
df['py-ios-weeknum'] = [d.isocalendar()[1] for d in df['date'].dt.date]
df['py-iso-year'] = [d.isocalendar()[0] for d in df['date'].dt.date]
df['week'] = df.date.apply(lambda x: x.week)
df['m'] = df.date.apply(lambda x: (x.isocalendar()[0], x.isocalendar()[1]))
df['weekpy'] = df.m.apply(lambda d: DT.datetime.strptime(str(d)+'-1', "(%Y, %W)-%w"))
print(df)
выходы
date datenum py-ios-weeknum py-iso-year week m weekpy
0 2018-12-28 52 52 2018 52 (2018, 52) 2018-12-24
1 2018-12-29 52 52 2018 52 (2018, 52) 2018-12-24
2 2018-12-30 52 52 2018 52 (2018, 52) 2018-12-24
3 2018-12-31 1 1 2019 1 (2019, 1) 2019-01-07
4 2019-01-01 1 1 2019 1 (2019, 1) 2019-01-07
5 2019-01-02 1 1 2019 1 (2019, 1) 2019-01-07
6 2019-01-03 1 1 2019 1 (2019, 1) 2019-01-07
7 2019-01-04 1 1 2019 1 (2019, 1) 2019-01-07
df['datenum'] = df['date'].dt.week
эквивалентно df['week'] = df.date.apply(lambda x: x.week)
, но использование аксессора Series.dt
быстрее (с точки зрения как записи, так и производительности), чем вызов лямбда-функции для каждого элемента в df.date
, что и делает apply
.
Учитывая Python datetime.date
(или datetime.datetime
), самый простой способ получить номер недели ISO - вызвать его isocalendar
метод :
In [76]: d = DT.datetime(2018,12,31)
In [87]: iso_year, iso_week_number, iso_weekday = d.isocalendar()
In [88]: print(iso_year, iso_week_number, iso_weekday)
2019 1 1
Обратите внимание, что 2018-12-31
соответствует году ISO 2019. Чтобы df['weekpy']
возвратил первый день недели ISO, вы должны указать год ISO , d.isocalendar()[0]
, а не фактический год,d.year
.
In [93]: print(DT.datetime.strptime('({}, {})-1'.format(d.year, pd.Timestamp(d).week), "(%Y, %W)-%w")) # WRONG
2018-01-01 00:00:00
In [94]: print(DT.datetime.strptime('({}, {})-1'.format(d.isocalendar()[0], d.isocalendar()[1]), "(%Y, %W)-%w")) # OK
2019-01-07 00:00:00