[PYTHON] Obtenez les nièmes valeurs les plus importantes dans Pandas

Obtenez les nièmes valeurs les plus importantes dans Pandas

Choses à faire

Obtenir les nièmes valeurs les plus importantes dans Pandas | Voyage d'auto-considération J'ai trouvé.

Lors du traitement de données à l'aide de Pandas DataFrame, vous pouvez facilement obtenir les valeurs maximales et minimales de chaque colonne à l'aide de méthodes telles que max et min. Cependant, pour le moment (pandas ver 1.1.2), il n'y a pas de fonction pour obtenir les deuxièmes valeurs maximales et minimales, les troisièmes valeurs maximales et minimales, etc. [...] Par conséquent, dans cet article, je vais présenter un script qui peut être utilisé avec le moins de lignes possible et peut obtenir la nième valeur supérieure de chaque colonne de DataFrame comme indiqué dans l'image ci-dessous.

En d'autres termes, lorsqu'il y a la trame de données suivante «df»,

import numpy as np
import pandas as pd

np.random.seed(0)
df = pd.DataFrame(np.random.permutation(50).reshape(10, 5))
df
0 1 2 3 4
0 28 11 10 41 2
1 27 38 31 22 4
2 33 35 26 34 18
3 7 14 45 48 29
4 15 30 32 16 42
5 20 43 8 13 25
6 5 17 40 49 1
7 12 37 24 6 23
8 36 21 19 9 39
9 46 3 0 47 44

Cela signifie que les pandas n'ont pas de fonction / méthode qui extrait les 3 supérieurs (ou inférieurs) pour chaque colonne et acquiert la trame de données suivante.

0 1 2 3 4
1 46 43 45 49 44
2 36 38 40 48 42
3 33 37 32 47 39

politique

Dans le bloc de données «df» donné dans cet exemple, toutes les colonnes ont le même type de données, mais comme les données réelles ont souvent des types de données différents pour chaque colonne, utilisez «df.apply ()» pour column. Pensez à traiter à chaque fois.

En d'autres termes, passez la série suivante s et

0
0 28
1 27
2 33
3 7
4 15
5 20
6 5
7 12
8 36
9 46

Nous allons créer une fonction qui renvoie la série suivante.

0
1 46
2 36
3 33

Méthode

Dans l'article cité, les fonctions suivantes sont affichées. Les arguments facultatifs sont les suivants.

--topnum: Nombre d'éléments à obtenir. La valeur par défaut est «3». --getmin: S'il est défini sur True, il sera acquis dans l'ordre croissant. La valeur par défaut est l'ordre décroissant. --getindex: Lorsqu'il est défini sur True, l'index est renvoyé à la place de la valeur.

def getmax(series, topnum=3, getmin=False, getindex=False):
    if getindex is False:
        series = (series.sort_values(ascending=getmin).head(topnum)
                  .reset_index(drop=True))
        series.index += 1
        return series
    else:
        return series.sort_values(ascending=getmin).head(topnum).index

Cette méthode trie d'abord la série entière (https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.sort_values.html) puis Get Top et réinitialiser l'index pour démarrer l'index 1 (https: // Je fais le travail d'ajouter 1 après pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.reset_index.html).

Mais ** ce ne serait pas **.

Pour obtenir le top n d'une série avec des pandas, [pd.Series.nlargset ()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series. nlargest.html) </ code> méthode (et [pd.Series.nsmallest ()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.nsmallest. html) </ code>) est la solution optimale.

%timeit df[0].sort_values(ascending=False).head(3)
%timeit df[0].nlargest(3)
0
9 46
8 36
2 33
299 µs ± 9.43 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
153 µs ± 1.58 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

C'est également deux fois plus rapide (bien que vous puissiez penser à utiliser NumPy pour la vitesse, mais c'est un peu moins concis dans votre code).

Il est également assez redondant d'ajouter un index de numéro de série à partir de 1. Là où vous pouvez définir directement le numéro de série à partir de 1, ajoutez 1 après avoir créé l'index à partir de 0. Vous pourriez penser à utiliser np.arange () ou range (), mais [pd.RangeIndex ()](https://pandas.pydata.org/pandas-docs/stable/reference/ Utilisez api / pandas.RangeIndex.html) </ code>.

test_s = pd._testing.makeStringSeries(10000)

%timeit s2 = test_s.reset_index(drop=True); s2.index += 1
%timeit s2 = test_s.set_axis(range(1, len(test_s)+1))
%timeit s2 = test_s.set_axis(np.arange(1, len(test_s)+1))
%timeit s2 = test_s.set_axis(pd.RangeIndex(1, len(test_s)+1))
109 µs ± 2.98 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
40.2 µs ± 1.02 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
64.7 µs ± 1.49 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
39.8 µs ± 931 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Conclusion

C'est pourquoi cela ressemble à ceci:

def getmax_rev(series, topnum=3, getmin=False, getindex=False):
    out = series.nsmallest(topnum) if getmin else series.nlargest(topnum)
    return out.index if getindex else out.set_axis(pd.RangeIndex(1, topnum+1))

Recommended Posts