I have a DataFrame that looks like this:
>>> df = pd.DataFrame({
'category1': list('AABAAB'),
'category2': list('xyxxyx'),
'year': [2000, 2000, 2000, 2002, 2002, 2002],
'value': [0, 1, 0, 4, 3, 4]
})
>>> df
category1 category2 year value
0 A x 2000 0
1 A y 2000 1
2 B x 2000 0
3 A x 2002 4
4 A y 2002 3
5 B x 2002 4
I'd like to expand the data to include missing years in a range. For example, if the range were range(2000, 2003), the expanded DataFrame should look like this:
category1 category2 year value
0 A x 2000 0.0
1 A y 2000 1.0
2 B x 2000 0.0
3 A x 2001 NaN
4 A y 2001 NaN
5 B x 2001 NaN
6 A x 2002 4.0
7 A y 2002 3.0
8 B x 2002 4.0
I have tried an approach using pd.MultiIndex.from_product, but that creates rows that aren't valid combinations of category1 and category2 (for example, B and y shouldn't go together). Using from_product and then filtering is too slow for my actual data, which includes many more combinations.
Is there an easier solution to this that can scale well?
Edit
This is the solution I ended up going with, trying to generalize the problem a bit:
id_cols = ['category1', 'category2']
df_out = (df.pivot_table(index=id_cols, values='value', columns='year')
.reindex(columns=range(2000, 2003))
.stack(dropna=False)
.sort_index(level=-1)
.reset_index(name='value'))
category1 category2 year value
0 A x 2000 0.0
1 A y 2000 1.0
2 B x 2000 0.0
3 A x 2001 NaN
4 A y 2001 NaN
5 B x 2001 NaN
6 A x 2002 4.0
7 A y 2002 3.0
8 B x 2002 4.0