Encuentra el máximo de dos o más columnas con pandas


101

Tengo una trama de datos con columnas A, B. Necesito crear una columna de Cmodo que para cada registro / fila:

C = max(A, B).

¿Cómo debo hacer esto?

Respuestas:


191

Puede obtener el máximo de esta manera:

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

y entonces:

>>> 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 sabe que "A" y "B" son las únicas columnas, incluso podría salirse con la suya.

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

Y a ti .apply(max, axis=1)también te vendría bien , supongo.


1
.apply(max, axis=1)es mucho más lento que.max(axis=1)
RajeshM

28

La respuesta de @ DSM está perfectamente bien en casi cualquier escenario normal. Pero si usted es el tipo de programador que quiere ir un poco más profundo que el nivel de la superficie, es posible que le interese saber que es un poco más rápido llamar a funciones numpy en la matriz subyacente .to_numpy()(o .valuespara <0.24) en lugar de directamente llamando a las funciones (cythonized) definidas en los objetos DataFrame / Series.

Por ejemplo, puede utilizar a lo ndarray.max()largo del primer eje.

# 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 sus datos tienen NaNs, necesitará 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 

También puede utilizar numpy.maximum.reduce. numpy.maximumes una ufunc (función universal) , y cada ufunc tiene unreduce :

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

ingrese la descripción de la imagen aquí

np.maximum.reducey np.maxparecen ser más o menos iguales (para la mayoría de DataFrames de tamaño normal), y resultan ser un poco más rápidos que DataFrame.max. Me imagino que esta diferencia permanece aproximadamente constante y se debe a la sobrecarga interna (alineación de indexación, manejo de NaN, etc.).

El gráfico se generó usando perfplot . Código de evaluación comparativa, como referencia:

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)

Pequeño error tipográfico: "df ['C'] = np.maximum.reduce (df ['A', 'B']]. Valores, eje = 1)" debe ser "df ['C'] = np.maximum. reduce (df [['A', 'B']]. valores, eje = 1) "
Velizar VESSELINOV
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.