144 votes

Trouver le maximum de deux ou plusieurs colonnes avec pandas

J'ai un cadre de données avec des colonnes A , B . Je dois créer une colonne C de sorte que pour chaque enregistrement / rangée :

C = max(A, B) .

Comment dois-je m'y prendre ?

259voto

DSM Points 71975

Vous pouvez obtenir le maximum comme ceci :

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

et ainsi de suite :

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

Si vous savez que "A" et "B" sont les seules colonnes, vous pouvez même vous en sortir avec

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

Et vous pourriez utiliser .apply(max, axis=1) aussi, je suppose.

42voto

coldspeed Points 111053

La réponse de @DSM est parfaite dans presque tous les scénarios normaux. Mais si vous êtes le type de programmeur qui veut aller un peu plus loin que le niveau de surface, vous serez peut-être intéressé de savoir qu'il est un peu plus rapide d'appeler des fonctions numpy sur le système sous-jacent .to_numpy() (ou .values pour <0.24) au lieu d'appeler directement les fonctions (cythonisées) définies sur les objets DataFrame/Series.

Par exemple, vous pouvez utiliser ndarray.max() le long du premier axe.

# 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 

Si vos données ont NaN vous aurez besoin de 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 

Vous pouvez également utiliser numpy.maximum.reduce . numpy.maximum es un ufunc (Fonction universelle) y chaque ufunc a un reduce :

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

enter image description here

np.maximum.reduce y np.max semblent être plus ou moins les mêmes (pour la plupart des DataFrames de taille normale) - et se trouvent être un peu plus rapides que les DataFrame.max . J'imagine que cette différence reste à peu près constante, et qu'elle est due à la surcharge interne (alignement de l'indexation, gestion des NaN, etc).

Le graphique a été généré en utilisant perfplot . Code d'évaluation comparative, pour référence :

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)

0voto

Mainland Points 1632

Pour trouver le maximum entre plusieurs colonnes, ce serait :

df[['A','B']].max(axis=1).max(axis=0)

Exemple :

df = 

                         A      B
timestamp                                
2019-11-20 07:00:16  14.037880  15.217879
2019-11-20 07:01:03  14.515359  15.878632
2019-11-20 07:01:33  15.056502  16.309152
2019-11-20 07:02:03  15.533981  16.740607
2019-11-20 07:02:34  17.221073  17.195145

print(df[['A','B']].max(axis=1).max(axis=0))
17.221073

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X