У меня есть фрейм данных, отсортированный по количеству, который дает мне 5 лучших категорий по имени, например:
| Name | Category | Amount |
|------|----------|--------|
| Abel | A | 9.2 |
| Abel | B | 3 |
| Abel | C | 2.5 |
| Abel | E | 2 |
| Abel | X | 0 |
| Cain | W | 93 |
| Cain | A | 2 |
|------|----------|--------|
Вот что я хочу в итоге:
| Name | Cat 1 | Cat 2 | Cat 3 | Cat 4 | Cat 5 |
|------|-------|-------|-------|-------|-------|
| Abel | A | B | C | E | X |
| Cain | W | A | - | - | - |
|------|-------|-------|-------|-------|-------|
Я попробовал df.pivot("Name","Category"), но он устанавливает значения (например, A, B,...) в качестве имен столбцов, но я хочу, чтобы 5 столбцов были предварительно определены как "Cat 1" на "Cat 5", поэтому я не уверен, что я могу сделать, чтобы получить результат сейчас. Кроме того, не все имена имеют 5 строк. Например, У Cain есть только верхние 2, что означает, что столбцы Cat 3, Cat 4 и Cat5 должны быть нулевыми или «-». Любая помощь? Спасибо!
Обновления:
Хорошо, так что, например. если все мои имена имеют запись только в 2 категориях, я все равно хочу получить 5 новых столбцов для 5 верхних категорий (т.е. Cat 1, Cat 2, Cat 3, Cat 4, Cat 5).
Теперь, если я сделаю
df["g"] = top5_jmi.groupby("Name").cumcount().add(1)
Это даст мне только 2 столбца, если я поверну их позже. Как я могу получить 5 столбцов? Например.
| Name | Category | Amount |
|------|----------|--------|
| Abel | A | 9.2 |
| Abel | B | 3 |
| Cain | W | 93 |
| Cain | A | 2 |
|------|----------|--------|
should still give me this:
| Name | Cat 1 | Cat 2 | Cat 3 | Cat 4 | Cat 5 |
|------|-------|-------|-------|-------|-------|
| Abel | A | B | - | - | - |
| Cain | W | A | - | - | - |
|------|-------|-------|-------|-------|-------|
Использовать:
#create counter column used for later columns names
df['g'] = df.groupby('Name').cumcount().add(1)
#filter top3
df = df[df['g'] <= 5]
#reshape by pivot
df2 = (df.pivot('Name','g','Category')
.add_prefix('Type ')
.reset_index()
.rename_axis(None, axis=1)
.fillna('-'))
print (df2)
Name Type 1 Type 2 Type 3 Type 4 Type 5
0 Abel A B C E X
1 Cain W A - - -
EDIT: используйте DataFrame.reindex
для добавления отсутствующих столбцов:
df['g'] = df.groupby('Name').cumcount().add(1)
#filter top3
df = df[df['g'] <= 5]
#reshape by pivot
df2 = (df.pivot('Name','g','Category')
.reindex(range(1, 6), axis=1)
.add_prefix('Type ')
.reset_index()
.rename_axis(None, axis=1)
.fillna('-'))
print (df2)
Name Type 1 Type 2 Type 3 Type 4 Type 5
0 Abel A B - - -
1 Cain W A - - -
@AhSheng - Не уверен, что понял, что такое алгоритм для пропуска первого или второго значения и получения только значений 3., 4., 5.? Можете ли вы объяснить больше?
Я думаю, что в примере значения данных для Cain
находятся в первом и втором столбцах, что следует изменить, например. 3. и 5. столбцы заполнены W
и A
?
Я только что проверил. Если все имена имеют только 1 тип или менее 5, будет только несколько столбцов, например. Тип 1, Тип 2 и не более. Но я все еще хочу иметь Тип 3, Тип 4, Тип 5 со всеми значениями как "-". Это происходит потому, что cumcount() основан на количестве строк в имени. Есть ли способ исправить это до 5 строк на имя и «-», если нет строк?