подсчитать частоту появления значения в столбце данных

313

У меня есть набор данных

|category|
cat a
cat b
cat a

Я хотел бы иметь возможность вернуть что-то вроде (показывая уникальные значения и частоту)

category | freq |
cat a       2
cat b       1
yoshiserry
источник
1
Попробуйтеcollections.Counter
metatoaster
94
Вы ищете df["category"].value_counts()?
DSM
При использовании "df [" category "]. Value_counts ()" он говорит, что это int? но он возвращает имя столбца в качестве индекса? Это объект dataframe или он как-то объединяет ряд (количество) и исходные уникальные значения столбца?
yoshiserry
@yoshiserry, это серия Панд, type(df['category'].value_counts())и она скажет так
EdChum
Я сделал, и я был удивлен этим, но это имеет смысл, чем больше я думаю об этом. После этого значение рассчитывается в некоторых столбцах, есть строки, которые я бы хотел исключить. Я знаю, как удалить столбцы, но как исключить строки?
yoshiserry

Ответы:

414

Используйте groupbyи count:

In [37]:
df = pd.DataFrame({'a':list('abssbab')})
df.groupby('a').count()

Out[37]:

   a
a   
a  2
b  3
s  2

[3 rows x 1 columns]

См. Онлайн-документы: http://pandas.pydata.org/pandas-docs/stable/groupby.html.

Также, value_counts()как прокомментировал @DSM, здесь можно найти много способов убрать кошку.

In [38]:
df['a'].value_counts()

Out[38]:

b    3
a    2
s    2
dtype: int64

Если вы хотите добавить частоту обратно к исходному фрейму данных, используйте transformдля возврата выровненного индекса:

In [41]:
df['freq'] = df.groupby('a')['a'].transform('count')
df

Out[41]:

   a freq
0  a    2
1  b    3
2  s    2
3  s    2
4  b    3
5  a    2
6  b    3

[7 rows x 2 columns]
EdChum
источник
@yoshiserry Нет, вы видите, что он создает серию, которая выравнивается с исходным кадром данных, в отличие от других методов, которые отображают уникальные значения и их частоту, если вы хотите просто добавить подсчет частоты обратно к кадру данных, вы можете использовать преобразование для этот. Это просто еще один метод, вы заметили, что он не свернул информационный фрейм после присваивания, и пропущенные значения отсутствуют. Также я думаю, что у Dataframes всегда есть индекс, я не думаю, что вы можете от него избавиться, только сбросить его, назначить новый или использовать столбец в качестве индекса
EdChum
4
В вашем первом примере кода df назначается как ожидалось, но эта строка: df.groupby ('a'). Count () возвращает пустой фрейм данных. Возможно ли, что этот ответ устарел с пандами 0.18.1? Также немного сбивает с толку то, что имя вашего столбца «a» совпадает со значением, которое вы ищете «a». Я бы отредактировал его сам, но так как код не работает для меня, я не уверен в своих изменениях.
Алекс
1
@ Алекс, ты прав, похоже, в последних версиях это больше не работает, мне кажется, что это ошибка, потому что я не понимаю, почему нет
EdChum
1
Почему бы не использовать df.['a'].value_counts().reset_index()вместо df.groupby('a')['a'].transform('count')?
тандем
1
@tandem, они делают разные вещи, вызов value_countsбудет генерировать счетчик частоты, если вы хотите добавить результат обратно в виде нового столбца против вашего исходного df, то вам придется использовать, transformкак описано в моем ответе.
EdChum
93

Если вы хотите применить ко всем столбцам, вы можете использовать:

df.apply(pd.value_counts)

Это позволит применить функцию агрегирования на основе столбцов (в данном случае value_counts) к каждому из столбцов.

Арран Кудбард-Белл
источник
10
Это самый простой ответ. Это должно быть наверху.
Джеффри Хосе
4
Этот ответ прост, но (я полагаю) applyоперация не использует преимущества, которые векторизовывает массивы Numpy в виде столбцов. В результате производительность может быть проблемой для больших наборов данных.
17
58
df.category.value_counts()

Эта короткая строчка кода даст вам желаемый результат.

Если в имени вашего столбца есть пробелы, вы можете использовать

df['category'].value_counts()
Сатьяджит Дхавале
источник
2
Или используйте [], если в имени столбца есть пробел. df['category 1'].value_counts()
Джейкоб Калакал Джозеф
19
df.apply(pd.value_counts).fillna(0)

value_counts - возвращает объект, содержащий количество уникальных значений

apply - считать частоту в каждом столбце. Если вы установите axis=1, вы получите частоту в каждом ряду

fillna (0) - сделать вывод более модным. Изменен NaN на 0

Роман Казаков
источник
1
Это очень полезно при подсчете вхождений значения в столбцах одной и той же строки !!
AMC
14

В 0.18.1 groupbyвместе с countне дает частоты уникальных значений:

>>> df
   a
0  a
1  b
2  s
3  s
4  b
5  a
6  b

>>> df.groupby('a').count()
Empty DataFrame
Columns: []
Index: [a, b, s]

Однако уникальные значения и их частоты легко определяются с помощью size:

>>> df.groupby('a').size()
a
a    2
b    3
s    2

С df.a.value_counts()отсортированными значениями (в порядке убывания, то есть сначала с наибольшим значением) возвращается по умолчанию.

Vidhya G
источник
5

Использование списка понимания и value_counts для нескольких столбцов в DF

[my_series[c].value_counts() for c in list(my_series.select_dtypes(include=['O']).columns)]

https://stackoverflow.com/a/28192263/786326

Шанкар АРУЛ - jupyterdata.com
источник
5

Если ваш DataFrame имеет значения того же типа, вы также можете установить его return_counts=Trueв numpy.unique () .

index, counts = np.unique(df.values,return_counts=True)

np.bincount () может быть быстрее, если ваши значения целые.

user666
источник
4

Без каких-либо библиотек вы могли бы сделать это вместо этого:

def to_frequency_table(data):
    frequencytable = {}
    for key in data:
        if key in frequencytable:
            frequencytable[key] += 1
        else:
            frequencytable[key] = 1
    return frequencytable

Пример:

to_frequency_table([1,1,1,1,2,3,4,4])
>>> {1: 4, 2: 1, 3: 1, 4: 2}
Timz95
источник
1

Вы также можете сделать это с пандами, сначала транслируя свои колонки в виде категорий, dtype="category"например:

cats = ['client', 'hotel', 'currency', 'ota', 'user_country']

df[cats] = df[cats].astype('category')

а затем позвонив describe:

df[cats].describe()

Это даст вам хорошую таблицу значений и немного больше :):

    client  hotel   currency    ota user_country
count   852845  852845  852845  852845  852845
unique  2554    17477   132 14  219
top 2198    13202   USD Hades   US
freq    102562  8847    516500  242734  340992
tsando
источник
0
n_values = data.income.value_counts()

Первый уникальный счетчик значений

n_at_most_50k = n_values[0]

Второй уникальный счетчик значений

n_greater_50k = n_values[1]

n_values

Вывод:

<=50K    34014
>50K     11208

Name: income, dtype: int64

Вывод:

n_greater_50k,n_at_most_50k:-
(11208, 34014)
РАХУЛ КУМАР
источник
0

@metatoaster уже указал на это. Перейти на Counter. Это пылает быстро.

import pandas as pd
from collections import Counter
import timeit
import numpy as np

df = pd.DataFrame(np.random.randint(1, 10000, (100, 2)), columns=["NumA", "NumB"])

Таймеры

%timeit -n 10000 df['NumA'].value_counts()
# 10000 loops, best of 3: 715 µs per loop

%timeit -n 10000 df['NumA'].value_counts().to_dict()
# 10000 loops, best of 3: 796 µs per loop

%timeit -n 10000 Counter(df['NumA'])
# 10000 loops, best of 3: 74 µs per loop

%timeit -n 10000 df.groupby(['NumA']).count()
# 10000 loops, best of 3: 1.29 ms per loop

Ура!

dragonfire_007
источник
0

Используйте этот код:

import numpy as np
np.unique(df['a'],return_counts=True)
Харшит Оберой
источник
0
your data:

|category|
cat a
cat b
cat a

решение:

 df['freq'] = df.groupby('category')['category'].transform('count')
 df =  df.drop_duplicates()
Рахул Джайн
источник
0

Я считаю, что это должно работать нормально для любого списка столбцов DataFrame.

def column_list(x):
    column_list_df = []
    for col_name in x.columns:
        y = col_name, len(x[col_name].unique())
        column_list_df.append(y)
return pd.DataFrame(column_list_df)

column_list_df.rename(columns={0: "Feature", 1: "Value_count"})

Функция «column_list» проверяет имена столбцов, а затем проверяет уникальность значений каждого столбца.

djoguns
источник
Вы можете добавить краткое объяснение того, как работает ваш код, чтобы улучшить ваш ответ.
ДобромирМ