Лучшие 3 элемента, которые будут отображаться в широком формате в панде - PullRequest
0 голосов
/ 23 мая 2018

У меня есть следующий фрейм данных

code    attribute   rank_count
394 Feminine    9
394 Fresh   9
394 Heavy   8
418 Soft    13
418 Fresh   12
418 Clean   11
539 Fresh   14
539 Soft    14
539 Feminine    11
555 Feminine    9
555 Heavy   8
555 Soft    7

Вышеуказанный фрейм данных имеет поле атрибутов с различными атрибутами для поля кода, они ранжируются в третьем столбце, теперь он мне нужен в приведенном ниже формате сверху 1top2 top 3, который должен выглядеть следующим образом:

code    top1    top2    top3
394 Feminine (9)    Fresh (9)   Heavy (8)
418 Soft(13)    Fresh (12)  Clean (11)
539 Fresh(14)   soft(14)    Feminine(11)

Атрибуты Я не могу использовать сводную таблицу, так как атрибутов много, я пытаюсь переставить данные топ3 способом

Ответы [ 2 ]

0 голосов
/ 23 мая 2018

Это один из способов использования collections.defaultdict.

from collections import defaultdict
from operator import itemgetter

d = defaultdict(list)

for code, attr, rank in df.itertuples(index=False):
    d[code].append((attr, rank))

d = {k: sorted(v, key=itemgetter(1), reverse=True)[:3] for k, v in d.items()}

res = pd.DataFrame(d).T.reset_index()

print(res)

   index              0            1               2
0    394  (Feminine, 9)   (Fresh, 9)      (Heavy, 8)
1    418     (Soft, 13)  (Fresh, 12)     (Clean, 11)
2    539    (Fresh, 14)   (Soft, 14)  (Feminine, 11)
3    555  (Feminine, 9)   (Heavy, 8)       (Soft, 7)

Вы можете изменить имена столбцов и при необходимости предоставить дополнительное форматирование.На мой взгляд, лучше идея хранить кортежи, чем преобразовывать числовые данные в строки.

Если вам действительно нужно строковое представление ...

Вы можете использовать pd.Series.apply:

for col in [0, 1, 2]:
    res[col] = res[col].apply(lambda x: '{0} ({1})'.format(x[0], x[1]))
0 голосов
/ 23 мая 2018

Вы можете использовать:

df = (df.sort_values(['code','rank_count'], ascending=(True, False))
       .assign(attribute=df['attribute'] + ' (' + df['rank_count'].astype(str) + ')', 
               g=df.groupby('code').cumcount() + 1)
       .query('g < 4')
       .set_index(['code','g'])['attribute']
       .unstack()
       .add_prefix('top')
       .rename_axis(None, axis=1)
       .reset_index())
print (df)
   code          top1        top2           top3
0   394  Feminine (9)   Fresh (9)      Heavy (8)
1   418     Soft (13)  Fresh (12)     Clean (11)
2   539    Fresh (14)   Soft (14)  Feminine (11)
3   555  Feminine (9)   Heavy (8)       Soft (7)

Объяснение :

  1. Первый sort_values на 2 столбца
  2. Объединить столбцы attribute с помощью rank_count, добавить новый столбец подсчета с помощью cumcount с assign
  3. При необходимости отфильтровать top 3 поquery
  4. Изменить на set_index и unstack
  5. add_prefix, rename_axis и reset_index для окончательной очистки DataFrame

РЕДАКТИРОВАНИЕ:

Раствор без assign:

df = df.sort_values(['code','rank_count'], ascending=(True, False))
df['attribute']=df['attribute'] + ' (' + df['rank_count'].astype(str) + ')'
df['g'] = df.groupby('code').cumcount() + 1

df = (df.query('g < 4')
       .set_index(['code','g'])['attribute']
       .unstack()
       .add_prefix('top')
       .rename_axis(None, axis=1)
       .reset_index())
print (df)
   code          top1        top2           top3
0   394  Feminine (9)   Fresh (9)      Heavy (8)
1   418     Soft (13)  Fresh (12)     Clean (11)
2   539    Fresh (14)   Soft (14)  Feminine (11)
3   555  Feminine (9)   Heavy (8)       Soft (7)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...