Думаю, для этого нужно 3 шага решения
1) извлечение Alphabates из данных и создание новых столбцов,
2) дублирование строк со значениями w.r.t и
3) маскировка с использованием единичной матрицы.
df = pd.DataFrame([{'B1': '1C', 'B2': '', 'B3': '', },
{'B1': '3A', 'B2': '1A', 'B3': ''},
{'B1': '41A', 'B2': '28A', 'B3': '3A'}])
B1 B2 B3
0 1C
1 3A 1A
2 41A 28A 3A
1) Извлечение букв из строк и присвоение их столбцам
df = df.merge(df.apply(lambda x: x.str.extract('([A-Za-z])')).add_prefix('U_'), left_index=True,right_index=True,how='outer')
Из:
B1 B2 B3 U_B1 U_B2 U_B3
0 1C C NaN NaN
1 3A 1A A A NaN
2 41A 28A 3A A A A
2) Вы можете попробовать duplicating the rows
кадра данных, где бы он не превышал 1 значение
# Duplicating the rows of dataframe
val = df[['U_B1','U_B2','U_B3']].notnull().sum(axis=1)
df1 = df.loc[np.repeat(val.index,val)]
-> 3) затем, сгруппировавшись по индексу, выберите только masked values of identity matrix
( np.identity ) w.r.t длины каждой группы.
df1[['U_B1','U_B2','U_B3']] = df1.groupby(df1.index)['U_B1','U_B2','U_B3'].apply(lambda x: x.dropna(axis=1).mask(np.identity(len(x))==0))
Из:
B1 B2 B3 U_B1 U_B2 U_B3
0 1C C
1 3A 1A A
1 3A 1A A
2 41A 28A 3A A
2 41A 28A 3A A
2 41A 28A 3A A