#python #pandas
#python #pandas
Вопрос:
Как вы можете объединить несколько строк в одном фрейме данных pandas по столбцу общего ключа, где мы допускаем фиксированное ограничение длины для любой объединенной строки строк (поскольку количество строк с заданным общим ключом в этом случае является переменным)?
Создайте фрейм данных подобной формы…
key x1 x2 x3
-------------
1 a1 a2 a3
1 b1 b2 b3
2 c1 c2 c3
3 d1 d2 d3
3 e1 e2 e3
3 f1 f2 f3
3 g1 g2 g3
....
и хотел бы изменить это на что-то вроде
key x11 x12 x13 x21 x22 x23 x31 x32 x33
-------------
1 a1 a2 a3 b1 b2 b3 NA NA NA
2 c1 c2 c3 NA NA NA NA NA NA
3 d1 d2 d3 e1 e2 e3 f1 f2 f3
....
где столбец xjk — это k-я функция j-й строки, имеющая тот же ключ, что и другие строки, сгруппированные в этой же строке до (в данном случае вручную установлено значение …) 3 на группу (но может потребоваться изменить позже, и может быть значением, превышающим количество группируемых строк (например, здесь 5), в этом случае его следует просто заполнить NAs). Обратите внимание, что когда количество группируемых отдельных исходных строк меньше максимального предела, мы заполняем значения NA, а когда строк слишком много, мы группируем только до максимального предела строк и удаляем остальное из фрейма данных. Также обратите внимание, что иногда в отдельной строке могут отсутствовать значения.
Есть предложения о том, как это можно сделать?
Ответ №1:
Использование groupby
и затем ravel
для выравнивания всех значений внутри группы:
lim = 5
df = df.set_index('key')
k = len(df.columns)
x = df.groupby(level=0).apply(
lambda z: z.iloc[:lim].values.ravel().tolist()
[np.nan]*(lim*k-z.size))
x = pd.DataFrame(x.tolist(), x.index)
x.columns = [f'x{1 i//k}{1 i%k}' for i in x.columns]
print(x)
Вывод:
x11 x12 x13 x21 x22 x23 x31 x32 x33 x41 x42 x43 x51 x52 x53
key
1 a1 a2 a3 b1 b2 b3 NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 c1 c2 c3 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 d1 d2 d3 e1 e2 e3 f1 f2 f3 g1 g2 g3 NaN NaN NaN
Комментарии:
1. Спасибо. Примечание для других, использующих этот вопрос, обратите внимание, что форматирование строки последней строки для обозначения столбцов будет работать только в python 3.6 , если все еще необходимо использовать python 2.7
'x{}{}.format((1 i//len(x)), (1 i%len(x)))'
.2. Извините, вы правы, я пропустил это требование. Обновил мой ответ
lim
переменной, которая устанавливает это ограничение. В основном нам нужно взять первыеlim
строки в приложении с.iloc[:lim]
3. @lampShadesDrifter: И спасибо, это очень хороший момент о f-строках в python 3.6
4. Как ни странно, этот код, похоже, не работает для меня (с использованием python 2.7) тестовый фрейм данных, созданный так, чтобы быть похожим на тот, что в исходном вопросе. Получение меток столбцов:
x11 x12 x13 x14 x15 x16 x17 x18 x19
. Я думаю, что последняя строка в данном коде должна быть чем-то вроде:x.columns = [f'x{1 i//len(df.columns)}{1 i%len(df.columns)}' for i in x.columns]
. Затем это дало мне результаты, показанные в этом ответе.5. Просматривая код и статистику по моим фактическим данным варианта использования, я не думаю, что этот ответ на самом деле работает для требования, что максимальное ограничение может быть значением, превышающим количество группируемых строк (что, как я теперь понимаю, не было явным в исходном вопросе и действительно лучше всего иллюстрировало примерный случай). Обратите внимание, в моем реальном варианте использования есть строки с ~ 33 столбцами в каждой, которые пытаются объединить (~ 7 отдельных строк на комбинацию).