Q:

Pandas Dataframe: convert unique row label into non-unique rows

I have this nested python dictionary,
poke_dic = {
      'Basic': {'Fire': ['Cyndaquil', 'Charmander', 'Torchic'],
                'Grass': ['Chikorita', 'Bulbasaur', 'Treecko'],
                'Water': ['Totodile', 'Squirtle', 'Mudkip']},
     'Evo1': {'Fire': ['Quilava', 'Chameleon', 'Combusken'],
              'Grass': ['Bayleef', 'Ivysaur', 'Grovyle'],
              'Water': ['Croconaw', 'Wartortle', 'Marshtomp']},
     'Evo2': {'Fire': ['Typhlosion', 'Charizard', 'Blaziken'],
              'Grass': ['Meganium', 'Venusaur', 'Sceptile'],
              'Water': ['Feraligatr', 'Blastoise', 'Swampert']}
}

When I converted it into a dataframe format, it yields this table
poke_df = pandas.DataFrame(poke_dic)
poke_df

As we can see, the column labels are the keys for the level-1 dictionary, and the row labels are the keys from the level-2. The data-type for the entry is array. I expect to explode the arrays and create a new row from the row label.
The expected output (first few rows) should be like this

Is there any command in pandas that allows me to do this? Or I have to manipulate the dictionary in the first place? Thanks in advance

A:

Option 1
Instead of creating a dataframe and manipulating the dataframe, you could start off with the correct dataframe.  The issue here is that I had to use enumerate in the comprehension to ensure index uniqueness.  You can reset that level if you'd like.  
pd.DataFrame({
    evolution: {
        (element, i): poke
        for element, pokes in types.items()
        for i, poke in enumerate(pokes)
    } 
    for evolution, types in poke_dic.items()
})

              Basic       Evo1        Evo2
Fire  0   Cyndaquil    Quilava  Typhlosion
      1  Charmander  Chameleon   Charizard
      2     Torchic  Combusken    Blaziken
Grass 0   Chikorita    Bayleef    Meganium
      1   Bulbasaur    Ivysaur    Venusaur
      2     Treecko    Grovyle    Sceptile
Water 0    Totodile   Croconaw  Feraligatr
      1    Squirtle  Wartortle   Blastoise
      2      Mudkip  Marshtomp    Swampert

Option 2
More comprension but with pd.concat 
pd.concat({
    ev: pd.Series(*zip(*(
        (p, e) for e, t in x.items() for p in t
    ))) for ev, x in poke_dic.items()
}, axis=1)

            Basic       Evo1        Evo2
Fire    Cyndaquil    Quilava  Typhlosion
Fire   Charmander  Chameleon   Charizard
Fire      Torchic  Combusken    Blaziken
Grass   Chikorita    Bayleef    Meganium
Grass   Bulbasaur    Ivysaur    Venusaur
Grass     Treecko    Grovyle    Sceptile
Water    Totodile   Croconaw  Feraligatr
Water    Squirtle  Wartortle   Blastoise
Water      Mudkip  Marshtomp    Swampert

To get exactly as OP wanted
pd.concat({
    ev: pd.Series(*zip(*(
        (p, e) for e, t in x.items() for p in t
    ))) for ev, x in poke_dic.items()
}, axis=1).rename_axis('Type').reset_index()

    Type       Basic       Evo1        Evo2
0   Fire   Cyndaquil    Quilava  Typhlosion
1   Fire  Charmander  Chameleon   Charizard
2   Fire     Torchic  Combusken    Blaziken
3  Grass   Chikorita    Bayleef    Meganium
4  Grass   Bulbasaur    Ivysaur    Venusaur
5  Grass     Treecko    Grovyle    Sceptile
6  Water    Totodile   Croconaw  Feraligatr
7  Water    Squirtle  Wartortle   Blastoise
8  Water      Mudkip  Marshtomp    Swampert

Option W/E
None of these options feel clean, so I keep at it until I feel good about it.  
pd.concat({k: pd.DataFrame(v) for k, v in poke_dic.items()}).T.stack() \
  .reset_index(1, drop=True).rename_axis('Type').reset_index()

    Type       Basic       Evo1        Evo2
0   Fire   Cyndaquil    Quilava  Typhlosion
1   Fire  Charmander  Chameleon   Charizard
2   Fire     Torchic  Combusken    Blaziken
3  Grass   Chikorita    Bayleef    Meganium
4  Grass   Bulbasaur    Ivysaur    Venusaur
5  Grass     Treecko    Grovyle    Sceptile
6  Water    Totodile   Croconaw  Feraligatr
7  Water    Squirtle  Wartortle   Blastoise
8  Water      Mudkip  Marshtomp    Swampert

Option similar to @Wen 
pd.DataFrame(
    np.column_stack([
        poke_df.index.repeat(3),
        np.array(poke_df.values.tolist()).transpose(0, 2, 1).reshape(-1, 3),
    ]),
    columns=['Type'] + poke_df.columns.tolist()
)

    Type       Basic       Evo1        Evo2
0   Fire   Cyndaquil    Quilava  Typhlosion
1   Fire  Charmander  Chameleon   Charizard
2   Fire     Torchic  Combusken    Blaziken
3  Grass   Chikorita    Bayleef    Meganium
4  Grass   Bulbasaur    Ivysaur    Venusaur
5  Grass     Treecko    Grovyle    Sceptile
6  Water    Totodile   Croconaw  Feraligatr
7  Water    Squirtle  Wartortle   Blastoise
8  Water      Mudkip  Marshtomp    Swampert

