Znajdź maksymalnie dwie lub więcej kolumn z pandami


105

Mam dataframe z kolumnami A, B. Muszę utworzyć taką kolumnę C, aby dla każdego rekordu / wiersza:

C = max(A, B).

Jak mam się do tego zabrać?

Odpowiedzi:


198

Możesz uzyskać maksimum w ten sposób:

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

a więc:

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

Jeśli wiesz, że „A” i „B” to jedyne kolumny, możesz nawet uciec

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

I .apply(max, axis=1)myślę, że ty też możesz użyć .


2
.apply(max, axis=1)jest znacznie wolniejszy niż.max(axis=1)
RajeshM

30

Odpowiedź @ DSM jest w porządku w prawie każdym normalnym scenariuszu. Ale jeśli jesteś typem programisty, który chce wejść trochę głębiej niż poziom powierzchniowy, możesz być zainteresowany, aby wiedzieć, że trochę szybciej jest wywoływać funkcje numpy na bazowej .to_numpy()(lub .values<0,24) tablicy zamiast bezpośrednio wywoływanie (cytonizowanych) funkcji zdefiniowanych w obiektach DataFrame / Series.

Na przykład możesz użyć ndarray.max()wzdłuż pierwszej osi.

# 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 

Jeśli Twoje dane mają NaNs, będziesz potrzebować 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 

Możesz także użyć numpy.maximum.reduce. numpy.maximumjest ufunc (Universal Function) , a każdy ufunc mareduce :

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

wprowadź opis obrazu tutaj

np.maximum.reducei np.maxwydają się być mniej więcej takie same (dla większości ramek DataFrame o normalnym rozmiarze) - i zdarzają się być odcień szybsze niż DataFrame.max. Wyobrażam sobie, że ta różnica z grubsza pozostaje stała i wynika z wewnętrznego narzutu (wyrównanie indeksowania, obsługa NaN itp.).

Wykres został wygenerowany za pomocą perfplot . Kod porównawczy, w celach informacyjnych:

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)

Mała literówka: „df ['C'] = np.maximum.reduce (df ['A', 'B']]. Wartości, oś = 1)” powinno mieć wartość „df ['C'] = np.maximum. redukcja (df [['A', 'B']]. wartości, oś = 1) "
Velizar VESSELINOV
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.