Tableau de fréquence pour une seule variable


97

Une dernière question pour les pandas débutants pour la journée: comment générer une table pour une seule série?

Par exemple:

my_series = pandas.Series([1,2,2,3,3,3])
pandas.magical_frequency_function( my_series )

>> {
     1 : 1,
     2 : 2, 
     3 : 3
   }

Beaucoup de recherches sur Google m'ont conduit à Series.describe () et pandas.crosstabs, mais ni l'un ni l'autre ne fait exactement ce dont j'ai besoin: une variable, compte par catégories. Oh, et ce serait bien si cela fonctionnait pour différents types de données: chaînes, entiers, etc.

Réponses:


153

Peut .value_counts()- être ?

>>> import pandas
>>> my_series = pandas.Series([1,2,2,3,3,3, "fred", 1.8, 1.8])
>>> my_series
0       1
1       2
2       2
3       3
4       3
5       3
6    fred
7     1.8
8     1.8
>>> counts = my_series.value_counts()
>>> counts
3       3
2       2
1.8     2
fred    1
1       1
>>> len(counts)
5
>>> sum(counts)
9
>>> counts["fred"]
1
>>> dict(counts)
{1.8: 2, 2: 2, 3: 3, 1: 1, 'fred': 1}

5
.value_counts().sort_index(1), pour éviter que la première colonne ne devienne légèrement en
désordre

9
Existe-t-il un équivalent pour DataFrame, plutôt que pour les séries? J'ai essayé d'exécuter .value_counts () sur un df et j'ai obtenuAttributeError: 'DataFrame' object has no attribute 'value_counts'
Mittenchops

1
Existe-t-il un moyen simple de convertir ces chiffres en proportions?
dsaxton le

7
@dsaxton vous pouvez utiliser .value_counts (normalize = True) pour convertir les résultats en proportions
Max Power

2
Pour l'utiliser à la place sur une trame de données, convertissez-la en une représentation de tableau numpy 1-D équivalente, comme - pd.value_counts(df.values.ravel())qui renvoie une série dont les attributs indexet valuescontiennent les éléments uniques et leurs nombres respectivement.
Nickil Maveli

11

Vous pouvez utiliser la compréhension de liste sur une trame de données pour compter les fréquences des colonnes en tant que telles

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

Panne:

my_series.select_dtypes(include=['O']) 

Sélectionne uniquement les données catégorielles

list(my_series.select_dtypes(include=['O']).columns) 

Transforme les colonnes d'en haut en une liste

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

Itère dans la liste ci-dessus et applique value_counts () à chacune des colonnes


5

La réponse fournie par @DSM est simple et directe, mais j'ai pensé ajouter ma propre contribution à cette question. Si vous regardez le code de pandas.value_counts , vous verrez qu'il se passe beaucoup de choses.

Si vous avez besoin de calculer la fréquence de nombreuses séries, cela peut prendre un certain temps. Une implémentation plus rapide serait d'utiliser numpy.unique avecreturn_counts = True

Voici un exemple:

import pandas as pd
import numpy as np

my_series = pd.Series([1,2,2,3,3,3])

print(my_series.value_counts())
3    3
2    2
1    1
dtype: int64

Notez ici que l'article retourné est un pandas.

En comparaison, numpy.uniquerenvoie un tuple avec deux éléments, les valeurs uniques et les décomptes.

vals, counts = np.unique(my_series, return_counts=True)
print(vals, counts)
[1 2 3] [1 2 3]

Vous pouvez ensuite les combiner dans un dictionnaire:

results = dict(zip(vals, counts))
print(results)
{1: 1, 2: 2, 3: 3}

Et puis dans un pandas.Series

print(pd.Series(results))
1    1
2    2
3    3
dtype: int64

0

pour la distribution de fréquence d'une variable avec des valeurs excessives, vous pouvez réduire les valeurs dans les classes,

Ici, j'ai des valeurs excessives pour la employratevariable, et il n'y a aucune signification de sa distribution de fréquence avec directvalues_count(normalize=True)

                country  employrate alcconsumption
0           Afghanistan   55.700001            .03
1               Albania   11.000000           7.29
2               Algeria   11.000000            .69
3               Andorra         nan          10.17
4                Angola   75.699997           5.57
..                  ...         ...            ...
208             Vietnam   71.000000           3.91
209  West Bank and Gaza   32.000000               
210         Yemen, Rep.   39.000000             .2
211              Zambia   61.000000           3.56
212            Zimbabwe   66.800003           4.96

[213 rows x 3 columns]

distribution de fréquence values_count(normalize=True)sans classification, la longueur du résultat ici est de 139 (semble dénuée de sens en tant que distribution de fréquence):

print(gm["employrate"].value_counts(sort=False,normalize=True))

50.500000   0.005618
61.500000   0.016854
46.000000   0.011236
64.500000   0.005618
63.500000   0.005618

58.599998   0.005618
63.799999   0.011236
63.200001   0.005618
65.599998   0.005618
68.300003   0.005618
Name: employrate, Length: 139, dtype: float64

en mettant la classification, nous mettons toutes les valeurs avec une certaine plage ie.

0-10 comme 1,
11-20 comme 2  
21-30 comme 3, et ainsi de suite.
gm["employrate"]=gm["employrate"].str.strip().dropna()  
gm["employrate"]=pd.to_numeric(gm["employrate"])
gm['employrate'] = np.where(
   (gm['employrate'] <=10) & (gm['employrate'] > 0) , 1, gm['employrate']
   )
gm['employrate'] = np.where(
   (gm['employrate'] <=20) & (gm['employrate'] > 10) , 1, gm['employrate']
   )
gm['employrate'] = np.where(
   (gm['employrate'] <=30) & (gm['employrate'] > 20) , 2, gm['employrate']
   )
gm['employrate'] = np.where(
   (gm['employrate'] <=40) & (gm['employrate'] > 30) , 3, gm['employrate']
   )
gm['employrate'] = np.where(
   (gm['employrate'] <=50) & (gm['employrate'] > 40) , 4, gm['employrate']
   )
gm['employrate'] = np.where(
   (gm['employrate'] <=60) & (gm['employrate'] > 50) , 5, gm['employrate']
   )
gm['employrate'] = np.where(
   (gm['employrate'] <=70) & (gm['employrate'] > 60) , 6, gm['employrate']
   )
gm['employrate'] = np.where(
   (gm['employrate'] <=80) & (gm['employrate'] > 70) , 7, gm['employrate']
   )
gm['employrate'] = np.where(
   (gm['employrate'] <=90) & (gm['employrate'] > 80) , 8, gm['employrate']
   )
gm['employrate'] = np.where(
   (gm['employrate'] <=100) & (gm['employrate'] > 90) , 9, gm['employrate']
   )
print(gm["employrate"].value_counts(sort=False,normalize=True))

après classification, nous avons une distribution de fréquence claire. ici on voit facilement que 37.64%des pays ont un taux d'emploi entre 51-60% et 11.79%des pays ont un taux d'emploi entre71-80%

5.000000   0.376404
7.000000   0.117978
4.000000   0.179775
6.000000   0.264045
8.000000   0.033708
3.000000   0.028090
Name: employrate, dtype: float64
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.