compter la fréquence à laquelle une valeur se produit dans une colonne de trame de données


313

J'ai un ensemble de données

|category|
cat a
cat b
cat a

J'aimerais pouvoir retourner quelque chose comme (montrant des valeurs et une fréquence uniques)

category | freq |
cat a       2
cat b       1


94

Lorsque vous utilisez "df [" category "]. Value_counts ()", il dit que c'est un int? mais il renvoie le nom de la colonne comme index? S'agit-il d'un objet de trame de données ou combine-t-il d'une manière ou d'une autre une série (les nombres) et les valeurs de colonne uniques d'origine?
yoshiserry

@yoshiserry c'est une série Pandas type(df['category'].value_counts())et ça le dira
EdChum

Je l'ai fait, et j'ai été surpris par cela, mais cela a du sens plus j'y pense. Après cela, la valeur compte sur certaines colonnes, il y a des lignes que j'aimerais exclure. Je sais comment supprimer des colonnes, mais comment exclure des lignes?
yoshiserry

Réponses:


414

Utiliser groupbyet 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]

Voir les documents en ligne: http://pandas.pydata.org/pandas-docs/stable/groupby.html

Aussi, value_counts()comme l'a commenté @DSM, de nombreuses façons de dépecer un chat ici

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

Out[38]:

b    3
a    2
s    2
dtype: int64

Si vous souhaitez ajouter de la fréquence à la trame de données d'origine, utilisez transformpour renvoyer un index aligné:

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]

@yoshiserry Non, ce que vous voyez, c'est qu'il crée une série qui s'aligne avec la trame de données d'origine, contrairement aux autres méthodes qui affichent les valeurs uniques et leur fréquence, si vous vouliez simplement ajouter un décompte de fréquence à la trame de données, vous pouvez utiliser la transformation pour ce. C'est juste une autre technique, vous remarquez qu'il n'a pas réduit la trame de données après l'affectation et qu'il n'y a pas de valeurs manquantes. Je pense aussi que les Dataframes ont toujours un index, je ne pense pas que vous puissiez vous en débarrasser, le réinitialiser uniquement, en affecter un nouveau ou utiliser une colonne comme index
EdChum

4
Dans votre premier exemple de code, df est affecté comme prévu, mais cette ligne: df.groupby ('a'). Count () renvoie une trame de données vide. Est-il possible que cette réponse soit obsolète avec les pandas 0.18.1? En outre, il est un peu déroutant que le nom de votre colonne «a» soit le même que la valeur que vous recherchez «a». Je le modifierais moi-même, mais comme le code ne fonctionne pas pour moi, je ne peux pas être sûr de mes modifications.
Alex

1
@Alex tu as raison, il semble que dans les dernières versions cela ne fonctionne plus, cela me semble être un bug car je ne vois pas pourquoi
EdChum

1
Pourquoi ne pas utiliser à la df.['a'].value_counts().reset_index()place de df.groupby('a')['a'].transform('count')?
tandem

1
@tandem, ils font des choses différentes, appeler value_countsgénérera un décompte de fréquences, si vous vouliez ajouter le résultat en tant que nouvelle colonne par rapport à votre df d'origine, vous devrez utiliser transformcomme détaillé dans ma réponse.
EdChum

93

Si vous souhaitez appliquer à toutes les colonnes, vous pouvez utiliser:

df.apply(pd.value_counts)

Cela appliquera une fonction d'agrégation basée sur les colonnes (dans ce cas value_counts) à chacune des colonnes.


10
C'est la réponse la plus simple. Cela devrait être au sommet.
Jeffrey Jose

4
Cette réponse est simple mais (je crois) l' applyopération ne tire pas parti des avantages offerts par les tableaux vectorisés Numpy sous forme de colonnes. Par conséquent, les performances pourraient être un problème sur des ensembles de données plus volumineux.
kuanb

58
df.category.value_counts()

Cette petite ligne de code courte vous donnera la sortie que vous souhaitez.

Si le nom de votre colonne contient des espaces, vous pouvez utiliser

df['category'].value_counts()

2
Ou utilisez [] si le nom de la colonne a de l'espace. df['category 1'].value_counts()
Jacob Kalakal Joseph

19
df.apply(pd.value_counts).fillna(0)

value_counts - Retourne un objet contenant des nombres de valeurs uniques

appliquer - compter la fréquence dans chaque colonne. Si vous définissez axis=1, vous obtenez la fréquence dans chaque ligne

fillna (0) - rendre la sortie plus sophistiquée. Changé NaN à 0


1
Ceci est très puissant lors du comptage des occurrences d'une valeur sur plusieurs colonnes pour la même ligne !!
amc

14

En 0.18.1 groupbyavec countne donne pas la fréquence des valeurs uniques:

>>> 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]

Cependant, les valeurs uniques et leurs fréquences sont facilement déterminées en utilisant size:

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

Avec les df.a.value_counts()valeurs triées (par ordre décroissant, c'est-à-dire la plus grande valeur en premier), elles sont renvoyées par défaut.



5

Si votre DataFrame a des valeurs du même type, vous pouvez également définir return_counts=Truedans numpy.unique () .

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

np.bincount () pourrait être plus rapide si vos valeurs sont des entiers.


4

Sans aucune bibliothèque, vous pouvez le faire à la place:

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

Exemple:

to_frequency_table([1,1,1,1,2,3,4,4])
>>> {1: 4, 2: 1, 3: 1, 4: 2}

1

Vous pouvez également le faire avec des pandas en diffusant d'abord vos colonnes en catégories, par dtype="category"exemple

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

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

puis en appelant describe:

df[cats].describe()

Cela vous donnera un joli tableau des nombres de valeurs et un peu plus :):

    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

0
n_values = data.income.value_counts()

Premier décompte de valeur unique

n_at_most_50k = n_values[0]

Deuxième compte de valeur unique

n_greater_50k = n_values[1]

n_values

Production:

<=50K    34014
>50K     11208

Name: income, dtype: int64

Production:

n_greater_50k,n_at_most_50k:-
(11208, 34014)

0

@metatoaster l'a déjà souligné. Allez-y Counter. C'est extrêmement rapide.

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"])

Minuteries

%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

À votre santé!



0
your data:

|category|
cat a
cat b
cat a

Solution:

 df['freq'] = df.groupby('category')['category'].transform('count')
 df =  df.drop_duplicates()

0

Je crois que cela devrait fonctionner correctement pour toute liste de colonnes 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"})

La fonction "liste_colonnes" vérifie les noms des colonnes, puis vérifie l'unicité des valeurs de chaque colonne.


Vous pouvez ajouter une brève explication du fonctionnement de votre code pour améliorer votre réponse.
DobromirM
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.