Я придумал довольно краткое решение, основанное на многоуровневой группировке, которая, по моему мнению, в значительной степени pandasonic .
Начнем с определения следующей функции: "разбиение "a Series , взятых из отдельных значений элемента на последовательность представлений списков, без окружающих [ и ] . Разделение происходит в каждом элементе '|' .:
def fn(grp1):
grp2 = (grp1 == '|').cumsum()
return grp1[grp1 != '|'].groupby(grp2).apply(lambda x: repr(list(x))[1:-1])
(будет использовано чуть позже).
Первый шаг обработки - преобразование id столбец в Series :
sId = df.id.apply(lambda x: pd.Series(x.split(','))).stack().rename('ID')
Для ваших данных результат:
0 0 1
1 2
2 3
3 4
Name: ID, dtype: object
Первый уровень MultiIndex - индексстроки-источника и второго уровня являются последовательными числами (в пределах текущей строки).
Теперь пришло время выполнить аналогичное преобразование столбца значений :
sVal = pd.DataFrame(df['values'].values.tolist(), index= df.index)\
.stack().groupby(level=0).apply(fn).rename('Values')
Результат:
0 0 ('a', 'b'), ('as', 'bd')
1 ('ss', 'dd'), ('ws', 'ee')
2 ('rr', 'rt'), ('tt', 'yy')
3 ('yu', 'uu'), ('ii', 'oo')
Name: Values, dtype: object
Обратите внимание, что вышеприведенный MultiIndex имеет ту же структуру, что и в случае sId .
И последний шаг - concat оба эти частичных результата:
result = pd.concat([sId, sVal], axis=1).reset_index(drop=True)
Результат:
ID Values
0 1 ('a', 'b'), ('as', 'bd')
1 2 ('ss', 'dd'), ('ws', 'ee')
2 3 ('rr', 'rt'), ('tt', 'yy')
3 4 ('yu', 'uu'), ('ii', 'oo')