Byłem bardzo zdezorientowany, jak definiowane są osie Pythona i czy odnoszą się do wierszy czy kolumn DataFrame. Rozważ poniższy kod:
>>> df = pd.DataFrame([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]], columns=["col1", "col2", "col3", "col4"])
>>> df
col1 col2 col3 col4
0 1 1 1 1
1 2 2 2 2
2 3 3 3 3
Więc jeśli zadzwonimy df.mean(axis=1)
, otrzymamy średnią między wierszami:
>>> df.mean(axis=1)
0 1
1 2
2 3
Jeśli jednak zadzwonimy df.drop(name, axis=1)
, faktycznie upuścimy kolumnę , a nie wiersz:
>>> df.drop("col4", axis=1)
col1 col2 col3
0 1 1 1
1 2 2 2
2 3 3 3
Czy ktoś może mi pomóc zrozumieć, co oznacza „oś” w pandach / numpy / scipy?
Na marginesie, DataFrame.mean
może być źle zdefiniowane. W dokumentacji jest napisane, DataFrame.mean
że axis=1
ma to oznaczać średnią nad kolumnami, a nie wierszami ...
mean
idrop
. Potrzeba nieliniowego myślenia, aby dojść do rzeczywistego zachowania.Odpowiedzi:
Być może najłatwiej jest zapamiętać to jako 0 = w dół i 1 = w poprzek .
To znaczy:
axis=0
do stosowania metody w każdej kolumnie lub do etykiet wierszy (indeksu).axis=1
do stosowania metody do każdego wiersza lub do etykiet kolumn.Oto rysunek przedstawiający części DataFrame, do których odwołuje się każda oś:
Warto również pamiętać, że Pandy podążają za użyciem tego słowa przez NumPy
axis
. Użycie jest wyjaśnione w słowniczku terminów NumPy :Tak więc, jeśli chodzi o metodę, o której mowa
df.mean(axis=1)
, wydaje się, że jest ona poprawnie zdefiniowana. Przyjmuje średnią wpisów poziomo w kolumnach , to znaczy wzdłuż każdego pojedynczego wiersza. Z drugiej stronydf.mean(axis=0)
byłaby to operacja działająca pionowo w dół w poprzek rzędów .Podobnie
df.drop(name, axis=1)
odnosi się do akcji na etykietach kolumn, ponieważ intuicyjnie przechodzą one przez oś poziomą. Określenieaxis=0
spowoduje, że metoda będzie działać na wierszach.źródło
df.apply
jako podobną do metody takiej jakdf.sum
. Na przykładdf.sum(axis=0)
sumuje każdą kolumnę DataFrame. Podobnie możesz napisać,df.apply(sum, axis=0)
aby wykonać dokładnie tę samą operację. Chociaż operacja jest rzeczywiście stosowana do każdej kolumny w DataFrame, rzeczywista funkcja biegnie w dół osi 0.MARGIN
(podobną doaxis
w pand) wartość „1” odpowiada „rzędów”, co oznacza, że funkcja jest stosowana do każdego rzędu , przy czym większa wartość „2” odnosi się do „kolumn”, co oznacza, że funkcja jest stosowana do każdej kolumny .Inny sposób wyjaśnienia:
// Not realistic but ideal for understanding the axis parameter df = pd.DataFrame([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]], columns=["idx1", "idx2", "idx3", "idx4"], index=["idx1", "idx2", "idx3"] ) ---------------------------------------1 | idx1 idx2 idx3 idx4 | idx1 1 1 1 1 | idx2 2 2 2 2 | idx3 3 3 3 3 0
O
df.drop
(oś oznacza pozycję)A: I wanna remove idx3. B: **Which one**? // typing while waiting response: df.drop("idx3", A: The one which is on axis 1 B: OK then it is >> df.drop("idx3", axis=1) // Result ---------------------------------------1 | idx1 idx2 idx4 | idx1 1 1 1 | idx2 2 2 2 | idx3 3 3 3 0
O
df.apply
(oś oznacza kierunek)A: I wanna apply sum. B: Which direction? // typing while waiting response: df.apply(lambda x: x.sum(), A: The one which is on *parallel to axis 0* B: OK then it is >> df.apply(lambda x: x.sum(), axis=0) // Result idx1 6 idx2 6 idx3 6 idx4 6
źródło
Są już prawidłowe odpowiedzi, ale podam inny przykład z> 2 wymiarami.
Parametr
axis
oznacza oś do zmiany .Na przykład weźmy pod uwagę, że istnieje ramka danych o wymiarze axbxc .
df.mean(axis=1)
zwraca ramkę danych o wymiarach ax 1 xc .df.drop("col4", axis=1)
zwraca ramkę danych o wymiarze ax (b-1) xc .Tutaj
axis=1
oznacza drugą oś, która jestb
, więcb
wartość zostanie zmieniona w tych przykładach.źródło
Powinno być szerzej znane, że aliasy ciągów „indeks” i „kolumny” mogą być używane zamiast liczb całkowitych 0/1. Aliasy są znacznie bardziej wyraźne i pomagają mi zapamiętać, jak przebiegają obliczenia. Innym aliasem dla „indeksu” są „wiersze” .
Kiedy
axis='index'
jest używane, obliczenia odbywają się w kolumnach, co jest mylące. Ale pamiętam to jako otrzymanie wyniku, który jest tego samego rozmiaru co inny wiersz.Wyświetlmy trochę danych na ekranie, aby zobaczyć, o czym mówię:
df = pd.DataFrame(np.random.rand(10, 4), columns=list('abcd')) a b c d 0 0.990730 0.567822 0.318174 0.122410 1 0.144962 0.718574 0.580569 0.582278 2 0.477151 0.907692 0.186276 0.342724 3 0.561043 0.122771 0.206819 0.904330 4 0.427413 0.186807 0.870504 0.878632 5 0.795392 0.658958 0.666026 0.262191 6 0.831404 0.011082 0.299811 0.906880 7 0.749729 0.564900 0.181627 0.211961 8 0.528308 0.394107 0.734904 0.961356 9 0.120508 0.656848 0.055749 0.290897
Kiedy chcemy wziąć średnią ze wszystkich kolumn, używamy,
axis='index'
aby uzyskać:df.mean(axis='index') a 0.562664 b 0.478956 c 0.410046 d 0.546366 dtype: float64
Ten sam wynik dałoby:
df.mean() # default is axis=0 df.mean(axis=0) df.mean(axis='rows')
Aby uzyskać operację od lewej do prawej na wierszach, użyj axis = 'columns'. Pamiętam to myśląc, że do mojej DataFrame można dodać dodatkową kolumnę:
df.mean(axis='columns') 0 0.499784 1 0.506596 2 0.478461 3 0.448741 4 0.590839 5 0.595642 6 0.512294 7 0.427054 8 0.654669 9 0.281000 dtype: float64
Ten sam wynik dałoby:
df.mean(axis=1)
Dodaj nowy wiersz z osią = 0 / indeks / wiersze
Wykorzystajmy te wyniki, aby dodać dodatkowe wiersze lub kolumny w celu uzupełnienia wyjaśnienia. Tak więc za każdym razem, gdy używasz axis = 0 / index / rows, jest to jak pobranie nowego wiersza DataFrame. Dodajmy wiersz:
df.append(df.mean(axis='rows'), ignore_index=True) a b c d 0 0.990730 0.567822 0.318174 0.122410 1 0.144962 0.718574 0.580569 0.582278 2 0.477151 0.907692 0.186276 0.342724 3 0.561043 0.122771 0.206819 0.904330 4 0.427413 0.186807 0.870504 0.878632 5 0.795392 0.658958 0.666026 0.262191 6 0.831404 0.011082 0.299811 0.906880 7 0.749729 0.564900 0.181627 0.211961 8 0.528308 0.394107 0.734904 0.961356 9 0.120508 0.656848 0.055749 0.290897 10 0.562664 0.478956 0.410046 0.546366
Dodaj nową kolumnę o osi = 1 / kolumny
Podobnie, gdy oś = 1 / kolumny utworzy dane, które można łatwo wprowadzić do własnej kolumny:
df.assign(e=df.mean(axis='columns')) a b c d e 0 0.990730 0.567822 0.318174 0.122410 0.499784 1 0.144962 0.718574 0.580569 0.582278 0.506596 2 0.477151 0.907692 0.186276 0.342724 0.478461 3 0.561043 0.122771 0.206819 0.904330 0.448741 4 0.427413 0.186807 0.870504 0.878632 0.590839 5 0.795392 0.658958 0.666026 0.262191 0.595642 6 0.831404 0.011082 0.299811 0.906880 0.512294 7 0.749729 0.564900 0.181627 0.211961 0.427054 8 0.528308 0.394107 0.734904 0.961356 0.654669 9 0.120508 0.656848 0.055749 0.290897 0.281000
Wygląda na to, że możesz zobaczyć wszystkie aliasy z następującymi zmiennymi prywatnymi:
df._AXIS_ALIASES {'rows': 0} df._AXIS_NUMBERS {'columns': 1, 'index': 0} df._AXIS_NAMES {0: 'index', 1: 'columns'}
źródło
Gdy oś = „rzędy” lub oś = 0, oznacza to dostęp do elementów w kierunku wierszy, od góry do dołu. Jeśli zastosujesz sumę wzdłuż osi = 0, da nam to sumy każdej kolumny.
Gdy oś = 'kolumny' lub oś = 1, oznacza to dostęp do elementów w kierunku kolumn, od lewej do prawej. Jeśli zastosujemy sumę wzdłuż osi = 1, otrzymamy sumy z każdego wiersza.
Wciąż mylące! Ale powyższe sprawia, że jest mi trochę łatwiej.
źródło
Wszystkie inne odpowiedzi są mylące. Oto jak o tym myślę:
Więc
df.drop(name, axis=1)
: upuszcza kolumnędf.mean(axis=1)
: oblicza kolumnę (wynik można dodać jako nową kolumnę)źródło