0

I have a pandas DataFrame object df as follow:

              P0  P1  P2  P3  P4  P5  P6   P7   P8   P9  P10  P11  P12  P13
object                                                                  
A            NaN NaN NaN NaN NaN NaN 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
B            NaN NaN NaN NaN NaN NaN NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
C            NaN NaN NaN NaN NaN NaN NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
D            NaN NaN NaN NaN NaN NaN NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
E            NaN NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0
F            NaN NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  NaN  1.0  1.0  1.0
G            NaN NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  NaN  NaN  1.0  1.0

for which I'd like to duplicate each using a list of suffixes:

              P0  P1  P2  P3  P4  P5  P6   P7   P8   P9  P10  P11  P12  P13
object                                                                  
A_XS         NaN NaN NaN NaN NaN NaN 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
A_S          NaN NaN NaN NaN NaN NaN 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
A_M          NaN NaN NaN NaN NaN NaN 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
A_L          NaN NaN NaN NaN NaN NaN 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
A_XL         NaN NaN NaN NaN NaN NaN 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
A            NaN NaN NaN NaN NaN NaN 1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
B_XS         NaN NaN NaN NaN NaN NaN NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
B_S          NaN NaN NaN NaN NaN NaN NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
B_M          NaN NaN NaN NaN NaN NaN NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
B_L          NaN NaN NaN NaN NaN NaN NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
B_XL         NaN NaN NaN NaN NaN NaN NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
B            NaN NaN NaN NaN NaN NaN NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
C_XS         NaN NaN NaN NaN NaN NaN NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
C_S          NaN NaN NaN NaN NaN NaN NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
C_M          NaN NaN NaN NaN NaN NaN NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
C_L          NaN NaN NaN NaN NaN NaN NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
C_XL         NaN NaN NaN NaN NaN NaN NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
C            NaN NaN NaN NaN NaN NaN NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
D_XS         NaN NaN NaN NaN NaN NaN NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
D_S          NaN NaN NaN NaN NaN NaN NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
D_M          NaN NaN NaN NaN NaN NaN NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
D_L          NaN NaN NaN NaN NaN NaN NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
D_XL         NaN NaN NaN NaN NaN NaN NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
D            NaN NaN NaN NaN NaN NaN NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
E            NaN NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0
F            NaN NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  NaN  1.0  1.0  1.0
G            NaN NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  NaN  NaN  1.0  1.0

The list of suffixes is: list_of_suffixes = ['XS', 'S', 'M', 'L', 'XL', ''] and the list of indexes that must be changed is: list_init = ['A', 'B', 'C', 'D'].
Notice E, F and G are left untouched from the original DataFrame.

From this answer: https://stackoverflow.com/a/50490890/6630397 I was able to duplicate the desired rows of my initial DataFrame df to the right number according to the length of the list list_of_suffixes:

list_init = ['A', 'B', 'C', 'D']
list_of_suffixes = ['XS', 'S', 'M', 'L', 'XL', '']
reps = [len(list_of_suffixes) if k in list_init else 1 for k in df.index]
df = df.loc[np.repeat(df.index.values, reps)]

But now all my DataFrame indices are an array of 10 of each A, B, C and D (except for E, F and G where there are only 1 row) where I'd like them to follow the pattern of suffixes from list_of_suffixes as shown here above.

How could I elegantly achieve that with good performances?

(note: if it's much better to work from a column containing the indexes it's also fine, because my objects A, B, C, D, E, F and G in the index column previously come from a standalone column named objects).

swiss_knight
  • 5,787
  • 8
  • 50
  • 92

1 Answers1

2

You should first compute a list containing the new indexes for each row, then explode that list:

newvals = [['{}{}'.format(i,j) for j in ('_' + k if k != '' else k
                                         for k in list_of_suffixes)]
           if i in list_init else [i] for i in df.index]
df.reset_index().assign(object=newvals).explode('object').set_index('object')

gives as expected:

        P0  P1  P2  P3  P4  P5   P6   P7   P8   P9  P10  P11  P12  P13
object                                                                
A_XS   NaN NaN NaN NaN NaN NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
A_S    NaN NaN NaN NaN NaN NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
A_M    NaN NaN NaN NaN NaN NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
A_L    NaN NaN NaN NaN NaN NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
A_XL   NaN NaN NaN NaN NaN NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
A      NaN NaN NaN NaN NaN NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
B_XS   NaN NaN NaN NaN NaN NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
B_S    NaN NaN NaN NaN NaN NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
B_M    NaN NaN NaN NaN NaN NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
B_L    NaN NaN NaN NaN NaN NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
B_XL   NaN NaN NaN NaN NaN NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
B      NaN NaN NaN NaN NaN NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
C_XS   NaN NaN NaN NaN NaN NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
C_S    NaN NaN NaN NaN NaN NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
C_M    NaN NaN NaN NaN NaN NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
C_L    NaN NaN NaN NaN NaN NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
C_XL   NaN NaN NaN NaN NaN NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
C      NaN NaN NaN NaN NaN NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
D_XS   NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
D_S    NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
D_M    NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
D_L    NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
D_XL   NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
D      NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
E      NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0
F      NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  NaN  NaN  1.0  1.0  1.0
G      NaN NaN NaN NaN NaN NaN  NaN  NaN  NaN  NaN  NaN  NaN  1.0  1.0
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252