Finden Sie das Maximum von zwei oder mehr Spalten mit Pandas

92

Ich habe einen Datenrahmen mit Spalten A, B. Ich muss eine Spalte Cso erstellen, dass für jeden Datensatz / jede Zeile:

C = max(A, B).

Wie soll ich das machen?

Navneet
quelle

Antworten:

182

Sie können das Maximum wie folgt erhalten:

>>> import pandas as pd
>>> df = pd.DataFrame({"A": [1,2,3], "B": [-2, 8, 1]})
>>> df
   A  B
0  1 -2
1  2  8
2  3  1
>>> df[["A", "B"]]
   A  B
0  1 -2
1  2  8
2  3  1
>>> df[["A", "B"]].max(axis=1)
0    1
1    8
2    3

und so:

>>> df["C"] = df[["A", "B"]].max(axis=1)
>>> df
   A  B  C
0  1 -2  1
1  2  8  8
2  3  1  3

Wenn Sie wissen, dass "A" und "B" die einzigen Spalten sind, könnten Sie sogar damit durchkommen

>>> df["C"] = df.max(axis=1)

Und du könntest es auch gebrauchen .apply(max, axis=1), denke ich.

DSM
quelle
1
.apply(max, axis=1)ist viel langsamer als.max(axis=1)
RajeshM
26

Die Antwort von @ DSM ist in fast jedem normalen Szenario vollkommen in Ordnung. Wenn Sie jedoch ein Programmierer sind, der etwas tiefer als bis zur Oberfläche gehen möchte, könnte es Sie interessieren, dass es etwas schneller ist, Numpy-Funktionen auf dem zugrunde liegenden Array .to_numpy()(oder .valuesfür <0,24) anstatt direkt aufzurufen Aufrufen der (cythonisierten) Funktionen, die für die DataFrame / Series-Objekte definiert sind.

Zum Beispiel können Sie ndarray.max()entlang der ersten Achse verwenden.

# Data borrowed from @DSM's post.
df = pd.DataFrame({"A": [1,2,3], "B": [-2, 8, 1]})
df
   A  B
0  1 -2
1  2  8
2  3  1

df['C'] = df[['A', 'B']].values.max(1)
# Or, assuming "A" and "B" are the only columns, 
# df['C'] = df.values.max(1) 
df

   A  B  C
0  1 -2  1
1  2  8  8
2  3  1  3 

Wenn Ihre Daten NaNs haben, benötigen Sie numpy.nanmax:

df['C'] = np.nanmax(df.values, axis=1)
df

   A  B  C
0  1 -2  1
1  2  8  8
2  3  1  3 

Sie können auch verwenden numpy.maximum.reduce. numpy.maximumist ein Ufunc (Universal Function) und jeder Ufunc hat einreduce :

df['C'] = np.maximum.reduce(df['A', 'B']].values, axis=1)
# df['C'] = np.maximum.reduce(df[['A', 'B']], axis=1)
# df['C'] = np.maximum.reduce(df, axis=1)
df

   A  B  C
0  1 -2  1
1  2  8  8
2  3  1  3

Geben Sie hier die Bildbeschreibung ein

np.maximum.reduceund np.maxscheinen mehr oder weniger gleich zu sein (für die meisten normal großen DataFrames) - und zufällig einen Schatten schneller als DataFrame.max. Ich stelle mir vor, dass dieser Unterschied in etwa konstant bleibt und auf internen Overhead (Indexausrichtung, Umgang mit NaNs usw.) zurückzuführen ist.

Der Graph wurde unter Verwendung eines Perfplots erzeugt . Benchmarking-Code als Referenz:

import pandas as pd
import perfplot

np.random.seed(0)
df_ = pd.DataFrame(np.random.randn(5, 1000))

perfplot.show(
    setup=lambda n: pd.concat([df_] * n, ignore_index=True),
    kernels=[
        lambda df: df.assign(new=df.max(axis=1)),
        lambda df: df.assign(new=df.values.max(1)),
        lambda df: df.assign(new=np.nanmax(df.values, axis=1)),
        lambda df: df.assign(new=np.maximum.reduce(df.values, axis=1)),
    ],
    labels=['df.max', 'np.max', 'np.maximum.reduce', 'np.nanmax'],
    n_range=[2**k for k in range(0, 15)],
    xlabel='N (* len(df))',
    logx=True,
    logy=True)
cs95
quelle
Kleiner Tippfehler: "df ['C'] = np.maximum.reduce (df ['A', 'B']]. Werte, Achse = 1)" sollte "df ['C'] = np.maximum sein. reduzieren (df [['A', 'B']]. Werte, Achse = 1) "
Velizar VESSELINOV