103

I would like to extract a week number from data in a pandas dataframe.

The date format is datetime64[ns]

I have normalized the date to remove the time from it

df['Date'] = df['Date'].apply(pd.datetools.normalize_date)

so the date now looks like - 2015-06-17 in the data frame column

and now I like to convert that to a week number.

starball
  • 20,030
  • 7
  • 43
  • 238
tony
  • 1,147
  • 2
  • 7
  • 10

7 Answers7

164

Just access the week attribute of Series.dt.isocalendar():

Example:

In [286]:
df['Date'].dt.isocalendar().week

Out[286]:
0    25
dtype: int64

In [287]:
df['Week_Number'] = df['Date'].dt.isocalendar().week
df

Out[287]:
        Date  Week_Number
0 2015-06-17           25
Nick ODell
  • 15,465
  • 3
  • 32
  • 66
EdChum
  • 376,765
  • 198
  • 813
  • 562
  • 4
    Note that the `week` property of the `Timestamp` object is ISO (8601) week of the year: https://github.com/pandas-dev/pandas/blob/bc9d329ba83795845be6aa455178e2f8d753542b/pandas/tests/scalar/timestamp/test_timestamp.py#L156 – tozCSS Jan 22 '20 at 17:48
  • 15
    Now this solution raises : FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead. – Adept Oct 19 '20 at 13:58
70

Here is another possibility using strftime. strftime.org is a good resource.

df['Week_Number'] = df['Date'].dt.strftime('%U')

'%U' represents the week number of the year (Sunday as the first day of the week) as a zero padded decimal number. All days in a new year preceding the first Sunday are considered to be in week 0.

If you have dates from multiple years, I recommend creating a Year-Week combination

df['Year-Week'] = df['Date'].dt.strftime('%Y-%U')
Axel
  • 2,545
  • 2
  • 18
  • 30
  • 6
    Best solution for me, since now, the accepted solution raises : FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead. – Adept Oct 19 '20 at 13:57
15

Pandas has its .dayofyear and .weekofyear functionality, which can be applied straight away to the output of pandas.to_datetime(df['column_name']), giving type "Timestamp" as the output.

import pandas as pd
df['formatted_date'] = pd.to_datetime(df['datetime'])
df['day_of_year'] = df.formatted_date.apply(lambda x: x.dayofyear)
df['week_of_year'] = df.formatted_date.apply(lambda x: x.weekofyear)
Sokolokki
  • 833
  • 1
  • 9
  • 19
  • FutureWarning: Series.dt.weekofyear and Series.dt.week have been deprecated. Please use Series.dt.isocalendar().week instead. ```df.formatted_date.dt.isocalendar().week``` – M at Dec 22 '22 at 17:42
  • @Mat I have just checked the answer on pandas 1.5.2 and got no warnings. Could you please confirm your pandas version? – Sokolokki Jan 02 '23 at 10:37
  • Dear @sokolokki, I'm using 1.5.2 too. Kindly take a look at this https://pandas.pydata.org/docs/reference/api/pandas.Series.dt.weekofyear.html – M at Jan 02 '23 at 15:47
3
from datetime import date
df_date = pd.DataFrame([date.today()],columns  = ['today'])
print(df_date)
#### Print Output ####
#        today
#0  2019-09-07
df_date['weeknum'] = df_date.today.apply(lambda x:x.isocalendar()[1])
print(df_date)
#### Print Output ####
#        today  weeknum
#0  2019-09-07       36
Klaus Smit
  • 31
  • 2
  • 7
    To improve this answer consider adding some text to support how this solves the problem. – haldo Sep 06 '19 at 16:00
3

Update to this answer
In my current python version (3.7, May 2021). The syntax df['Date'].dt.week is printing the following warning: FutureWarning: weekofyear and week have been deprecated, please use DatetimeIndex.isocalendar().week instead The way to use DatetimeIndex would be: df['week_number'] = pd.DatetimeIndex(df.index).isocalendar().week
Here a small demonstration of its use to return a Series

# Input
time_idx = pd.date_range('2022-01-01', periods=4, freq='H').tz_localize('UTC')
values = [9 , 8, 7, 6]

df1 = pd.DataFrame(data = values, index=time_idx, columns=['vals'])
# FutureWarning: weekofyear and week have been deprecated
df1['week_number'] = df1.index.week 

# Using DatetimeIndex.isocalendar().week instead
df2 = pd.DataFrame(data = values, index=time_idx, columns=['vals']) 
# Does not throws a warning
df2['week_number'] = pd.DatetimeIndex(df2.index).isocalendar().week 

print(df2)
eliasmaxil
  • 530
  • 4
  • 13
0

In case of pandas:

import random
import pandas as pd

desired_length = 100
desired_frequency="20D" # XXXM: XXX months, "XXXD":XXX days, XXXMin: XXX minutes etc.

index = pd.date_range('2020-01-01', periods=desired_length, freq=desired_frequency)
data = [random.random() for _ in range(len(index))]

df = pd.DataFrame(data=data, index=index, columns=['DATA'])
df[df.index.isocalendar().keys()] = df.index.isocalendar()
Shivid
  • 1,295
  • 1
  • 22
  • 36
0

isocalendar() assigns the week number 1 to the first calendar week of a year containing a Thursday:
https://docs.python.org/3/library/datetime.html#datetime.date.isocalendar

strftime('%U') and strftime('%W') assign the week number 1 to the first calendar week of a year containing a Sunday and Monday, respectively:
https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes

If a return value of the Excel function WEEKNUM(..., return_type=1) is the desired output, use strftime('%U').astype(int) + 1:
https://support.microsoft.com/en-us/office/weeknum-function-e5c43a03-b4ab-426c-b411-b18c13c75340

=========

idx_dt = pd.date_range('2021-12-31', periods=7, freq='D')
df = pd.DataFrame(
    {
        'Weekday (str)': idx_dt.strftime('%Y-%m-%d (%a)'),
        'Weeknum (isocalendar)': idx_dt.isocalendar().week,
        'Weeknum (%U)': idx_dt.strftime('%U').astype(int),
        'Weeknum (Excel)': [53, 1, 2, 2, 2, 2, 2],
    },
    index=idx_dt)
Weekday (str)   Weeknum (isocalendar)   Weeknum (%U)    Weeknum (Excel)
2021-12-31 (Fri)        52              52              53
2022-01-01 (Sat)        52              0               1
2022-01-02 (Sun)        52              1               2
2022-01-03 (Mon)        1               1               2
2022-01-04 (Tue)        1               1               2
2022-01-05 (Wed)        1               1               2
2022-01-06 (Thu)        1               1               2
J. Choi
  • 1,616
  • 12
  • 23