Really, I think the most elegant way is to perform the conversion in SQL:
sql = "SELECT DATE_ADD(MAKEDATE(y, 1), INTERVAL w WEEK) as date, d FROM test.t"
df = pd.read_sql(sql, engine)
print(df)
yields
date d
0 2009-01-08 10
1 2009-01-15 15
To do the equivalent in Python requires more boiler-plate since AFAIK Pandas does not provide any out-of-the-box facilities for converting years and week numbers into dates. You could of course use loops and the datetime module to convert the numbers into datetime.datetime objects one-by-one.
A faster way would be to use NumPy's datetime64 and timedelta64 dtypes to do the date arithmetic as NumPy arrays:
sql = "SELECT y, w, d FROM t"
df = pd.read_sql(sql, engine)
date = (df['y'].astype('<i8')-1970).view('<M8[Y]')
delta = (df['w'].astype('<i8')*7).view('<m8[D]')
df['date'] = date+delta
df = df[['date', 'd']]
print(df)
yields
date d
0 2009-01-08 10
1 2009-01-15 15
Edit: Building off of Hadi's answer in the comment, it's also possible to compute the date in SQL using MySQL's STR_TO_DATE function:
sql = "SELECT STR_TO_DATE(CONCAT(y,':',w,':1'), '%x:%v:%w') as date, d FROM test.t"
df = pd.read_sql(sql, engine)
which yields
date d
0 2008-12-29 10
1 2009-01-05 15
Note that according the the MySQL docs, %v
, means
Week (01..53), where Monday is the first day of the week; WEEK() mode 3; used with %x
and later on the same page, mode 3 means
Mode First day of week Range Week 1 is the first week …
3 Monday 1-53 with 4 or more days this year
For mode values with a meaning of “with 4 or more days this year,”
weeks are numbered according to ISO 8601:1988.
So if you want the week number to be consistent with ISO 8601:1988, then with STR_TO_DATE
you should use %v
(or %u
), not %V
(or %U
).
Note that my first answer above does not interpret the week as an ISO 8601 week number; it merely computes 7 days from Jan 1 for each week.