Fill a pandas dataframe (of predetermined size) with results from a similar dataframe (of size less than or equivalent to the original)
You can create the index directly:
pd.MultiIndex.from_product(
    (shop_ids, range(max_timebins + 1)), names=(&quot;shop&quot;, &quot;timebin&quot;)
)

Here is how you can achieve the same result (including the full index even if there is no data) in a simpler way:
import pandas as pd

# Specify the complete list of possible time bins
max_timebins = 3

# Specify the complete list of shops
shop_ids = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;]

target_index = pd.MultiIndex.from_product(
    (shop_ids, range(max_timebins + 1)), names=(&quot;shop&quot;, &quot;timebin&quot;)
)

# Example of a result of a query
dfq = pd.DataFrame(
    {
        &quot;shop&quot;: [&quot;A&quot;, &quot;A&quot;, &quot;A&quot;, &quot;A&quot;, &quot;B&quot;, &quot;B&quot;, &quot;C&quot;, &quot;C&quot;, &quot;C&quot;, &quot;D&quot;],
        &quot;time_bins&quot;: [0, 1, 2, 3, 0, 3, 0, 2, 3, 2],
        &quot;counts&quot;: [100, 220, 300, 440, 500, 660, 120, 340, 90, 400],
    }
).set_index([&quot;shop&quot;, &quot;time_bins&quot;])

result_df = dfq.reindex(target_index, fill_value=pd.NA)

print(result_df)

Output:
             counts
shop timebin       
A    0          100
     1          220
     2          300
     3          440
B    0          500
     1         &lt;NA&gt;
     2         &lt;NA&gt;
     3          660
C    0          120
     1         &lt;NA&gt;
     2          340
     3           90
D    0         &lt;NA&gt;
     1         &lt;NA&gt;
     2          400
     3         &lt;NA&gt;

There might be a better solution, but that would require knowing a bit more context.