'Adding new multiindex level

I have a DataFrame:

d = pd.DataFrame({'i1': ['A', 'B', 'C', 'D', 'E'],
                  'i2': ['I', 'II', 'III', 'IV', 'V'],
                  'val': ["lol1", "lol2", "lol3", "lol4", "lol5"]}).set_index(["i1", "i2"])
         val
i1 i2       
A  I    lol1
B  II   lol2
C  III  lol3
D  IV   lol4
E  V    lol5

I need to add new index level i3 from values [5, 10, 15], using pandas API, so it looks like:

            val
i1 i2  i3      
A  I   5   lol1
       10  lol1
       15  lol1
B  II  5   lol2
       10  lol2
       15  lol2
C  III 5   lol3
       10  lol3
       15  lol3
D  IV  5   lol4
       10  lol4
       15  lol4
E  V   5   lol5
       10  lol5
       15  lol5

My tries(ugly):

d = np.repeat(d.reset_index().values, 3, 0)

i3 = [5, 10, 15]
r2 = np.tile(i3, 5)

r = np.concatenate([d, r2.reshape(-1, 1)], 1)

d = pd.DataFrame(r, columns=["i1", "i2", "val", "i3"])
d = d.set_index(["i1", "i2", "i3"])

Also, I've been looking towards pd.MultiIndex.from_product, but it's going to make combinations from i1 and i2 no matter what I do.



Solution 1:[1]

Create list of tuples by values from MultiIndex, then use DataFrame.reindex with MultiIndex.from_tuples:

vals = [5, 10, 15]
tups = [x + (i,) for x in d.index for i in vals]
d = d.reindex(pd.MultiIndex.from_tuples(tups, names=['i1','i2','i3']))
print (d)
            val
i1 i2  i3      
A  I   5   lol1
       10  lol1
       15  lol1
B  II  5   lol2
       10  lol2
       15  lol2
C  III 5   lol3
       10  lol3
       15  lol3
D  IV  5   lol4
       10  lol4
       15  lol4
E  V   5   lol5
       10  lol5
       15  lol5

Solution 2:[2]

As an alternative to reindexing we can also create a new list column and explode.

d_new = (d.assign(i3=[[5, 10, 15]] * len(d))
          .explode("i3")
          .set_index("i3", append=True))

print(df_new)

# result:
            val
i1 i2  i3      
A  I   5   lol1
       10  lol1
       15  lol1
B  II  5   lol2
       10  lol2
       15  lol2
C  III 5   lol3
       10  lol3
       15  lol3
D  IV  5   lol4
       10  lol4
       15  lol4
E  V   5   lol5
       10  lol5
       15  lol5

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jezrael
Solution 2 mcsoini