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:
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ć .
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
i np.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)
.apply(max, axis=1)
jest znacznie wolniejszy niż.max(axis=1)