Python: получить счетчик частоты на основе двух столбцов (переменных) в кадре данных pandas в некоторых приложениях строк

93

Здравствуйте, у меня есть следующий фрейм данных.

    Group           Size

    Short          Small
    Short          Small
    Moderate       Medium
    Moderate       Small
    Tall           Large

Я хочу подсчитать, сколько раз одна и та же строка появляется в кадре данных.

    Group           Size      Time

    Short          Small        2
    Moderate       Medium       1 
    Moderate       Small        1
    Tall           Large        1
emax
источник
1
Примечание по производительности, включая альтернативы: Pandas groupby.size vs series.value_counts vs collections.Counter с несколькими сериями
jpp

Ответы:

145

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

In [11]: df.groupby(["Group", "Size"]).size()
Out[11]:
Group     Size
Moderate  Medium    1
          Small     1
Short     Small     2
Tall      Large     1
dtype: int64

In [12]: df.groupby(["Group", "Size"]).size().reset_index(name="Time")
Out[12]:
      Group    Size  Time
0  Moderate  Medium     1
1  Moderate   Small     1
2     Short   Small     2
3      Tall   Large     1
Энди Хайден
источник
7
Спасибо. Одно незначительное дополнение для выбора верхних k (= 20) значений на основе частоты ("Время"): df.groupby (["Группа", "Размер"]). Size (). Reset_index (name = "Time") .sort_values ​​(по = 'Время', по возрастанию = Ложь) .head (20);
Дилип Кумар Патчиголла
1
Просто обратите внимание, что использование .size()возвращает Series, а .size().reset_index(name="Time")является DataFrame. Спасибо, Энди.
alemol
или вы могли бы сделать df.groupby(by=["Group", "Size"], as_index=False).size()просто
Навин Кумар
51

Обновление после того, как pandas 1.1value_countsтеперь принимает несколько столбцов

df.value_counts(["Group", "Size"])

Вы также можете попробовать pd.crosstab()

Group           Size

Short          Small
Short          Small
Moderate       Medium
Moderate       Small
Tall           Large

pd.crosstab(df.Group,df.Size)


Size      Large  Medium  Small
Group                         
Moderate      0       1      1
Short         0       0      2
Tall          1       0      0

РЕДАКТИРОВАТЬ: Чтобы получить ваш выход

pd.crosstab(df.Group,df.Size).replace(0,np.nan).\
     stack().reset_index().rename(columns={0:'Time'})
Out[591]: 
      Group    Size  Time
0  Moderate  Medium   1.0
1  Moderate   Small   1.0
2     Short   Small   2.0
3      Tall   Large   1.0
BEN_YO
источник
7
отлично. вы даже можете добавить, margins=Trueчтобы получить маржинальный счет!
Мэтт Хэнкок
0

Другая возможность - использование .pivot_table()иaggfunc='size'

df_solution = df.pivot_table(index=['Group','Size'], aggfunc='size')
asantz96
источник