Kevin Kevin - 6 months ago 58
Python Question

Python datetime weekday strftime() vs weekday()

Have a pandas dataframe df, in order to get weekday from the date column, I did:

df_raw['DayOfWeek'] = df_raw[str_date_colname].dt.strftime('%w')


It returns weekday as a decimal number, where 0 is Sunday and 6 is Saturday. However, I want to get 0 is Monday and 6 is Sunday. So I did:

df_raw['DayOfWeek'] = df_raw[str_date_colname].dt.weekday()


But it returns:
'Series' object is not callable


May I know why? I think both
strftime()
and
weekday()
are callable in datetime objects: https://docs.python.org/2/library/datetime.html

Answer

If df is a Pandas DataFrame, then df['date'] is a Series. If df['date'] contains datetimes (in particular, if the dtype is datetime64[ns]s) then the Series will have a .dt accessor.

In [12]: type(df['date'])
Out[12]: pandas.core.series.Series

In [13]: type(df['date'].dt)
Out[13]: pandas.tseries.common.DatetimeProperties

The DatetimeProperties object returned by df['date'].dt has a weekday property (not a method). Properties are accessed without parentheses, so simply use df['date'].dt.weekday rather than df['date'].dt.weekday().


For example,

import pandas as pd
df = pd.DataFrame({'date': pd.date_range('2000-1-1', periods=7)})
df['dow'] = df['date'].dt.strftime('%w')
df['dow2'] = df['date'].dt.weekday
df['dow3'] = df['date'].dt.strftime('%a')

yields

        date dow  dow2 dow3
0 2000-01-01   6     5  Sat
1 2000-01-02   0     6  Sun
2 2000-01-03   1     0  Mon
3 2000-01-04   2     1  Tue
4 2000-01-05   3     2  Wed
5 2000-01-06   4     3  Thu
6 2000-01-07   5     4  Fri

It's commonly said that "Everything in Python is an object". Therefore it's very important to understand the type of each object since that determines what methods and attributes that object will have. The documentation you linked to, shows the methods available for datetime.datetime objects. Since df['date'].dt is a pandas.tseries.common.DatetimeProperties object, it has different attributes.


Whenever you see an error message of the form

blahblah object is not callable

Python is telling you it found an object, obj, of type blahblah followed by parentheses -- i.e. it encountered obj(...) where type(obj) is blahblah. The parentheses cause Python to call the object. Thus, it is complaining that obj is not callable.

So to hunt down the source of the problem in the future, find the line mentioned in the full traceback error message and look for parentheses.

df_raw['DayOfWeek'] = df_raw[str_date_colname].dt.weekday()

The object immediately in front of those parentheses should be of type blahblah. For example, df_raw[str_date_colname].dt.weekday is of type Series. You'll then know the source of the problem. Once you know that df_raw[str_date_colname].dt.weekday is a Series, you'll be curious to see what its values are, and then you'll discover it is already the values you are looking for.