[PYTHON] Holen Sie sich die besten n-ten Werte in Pandas

Holen Sie sich die besten n-ten Werte in Pandas

Dinge die zu tun sind

Den höchsten n-ten Wert in Pandas | Self-Consideration Journey erhalten Ich fand.

Wenn Sie Daten mit Pandas DataFrame verarbeiten, können Sie mit Methoden wie max und min problemlos die Maximal- und Minimalwerte jeder Spalte abrufen. Derzeit (pandas ver 1.1.2) gibt es jedoch keine Funktion, um die zweiten Maximal- und Minimalwerte, die dritten Maximal- und Minimalwerte usw. zu erhalten. [...] Daher werde ich in diesem Artikel ein Skript vorstellen, das mit so wenig Zeilen wie möglich verwendet werden kann und den oberen n-ten Wert jeder Spalte von DataFrame erhält, wie in der folgenden Abbildung gezeigt.

Mit anderen Worten, wenn es den folgenden Datenrahmen "df" gibt,

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

Dies bedeutet, dass Pandas keine Funktion / Methode haben, die die oberen (oder unteren) 3 für jede Spalte extrahiert und den folgenden Datenrahmen erfasst.

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

Politik

In dem in diesem Beispiel angegebenen Datenrahmen "df" haben alle Spalten den gleichen Datentyp. Da die tatsächlichen Daten jedoch häufig unterschiedliche Datentypen für jede Spalte haben, verwenden Sie "df.apply ()" für die Spalte. Betrachten Sie die Verarbeitung jedes Mal.

Mit anderen Worten, übergeben Sie die folgenden Serien s und

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

Wir werden eine Funktion erstellen, die die folgenden Reihen zurückgibt.

0
1 46
2 36
3 33

Methode

In dem zitierten Artikel werden die folgenden Funktionen gezeigt. Die optionalen Argumente lauten wie folgt.

--topnum: Anzahl der zu beschaffenden Gegenstände. Der Standardwert ist "3". --getmin: Wenn "True" eingestellt ist, wird es in aufsteigender Reihenfolge erfasst. Die Standardeinstellung ist absteigende Reihenfolge. --getindex: Bei der Einstellung True wird der Index anstelle des Werts zurückgegeben.

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

Diese Methode sortiert zuerst die gesamte Serie (https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.sort_values.html) und dann Get Top und Index zurücksetzen, um Index 1 zu starten (https: // Ich mache die Arbeit, 1 nach pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.reset_index.html hinzuzufügen.

Aber ** das wäre nicht **.

pd.Series.nlargset (), um das Top-n aus einer Serie mit Pandas zu erhalten. nlargest.html) </ code> -Methode (und [pd.Series.nsmallest ()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.nsmallest. html) </ code> Methode) ist die optimale Lösung.

%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)

Es ist auch doppelt so schnell (beachten Sie, dass Sie NumPy für die Geschwindigkeit in Betracht ziehen könnten, aber es ist etwas weniger präzise in Ihrem Code).

Es ist auch ziemlich redundant, einen Seriennummernindex ab 1 hinzuzufügen. Wenn Sie die Seriennummer direkt ab 1 festlegen können, fügen Sie 1 hinzu, nachdem Sie den Index ab 0 erstellt haben. Sie könnten an die Verwendung von "np.arange ()" oder "range ()" denken, aber pd.RangeIndex () Verwenden Sie 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)

Fazit

Deshalb sieht es so aus:

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