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ć?
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ć .
.apply(max, axis=1)
jest znacznie wolniejszy niż.max(axis=1)
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ą
NaN
s, 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.maximum
jest 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
np.maximum.reduce
inp.max
wydają 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)
źródło