Jestem tak pomylony z różnymi metodami indeksowania iloc
używanymi w pandach.
Powiedzmy, że próbuję przekonwertować ramkę danych 1-d na ramkę danych 2-d. Najpierw mam następującą 1-d ramkę danych
a_array = [1,2,3,4,5,6,7,8]
a_df = pd.DataFrame(a_array).T
Zamierzam przekonwertować to na 2-d ramkę danych o rozmiarze 2x4
. Zaczynam od przygotowania dwuwymiarowej ramki danych w następujący sposób:
b_df = pd.DataFrame(columns=range(4),index=range(2))
Następnie używam pętli for, aby pomóc mi w konwersji a_df
(1-d) na b_df
(2-d) za pomocą następującego kodu
for i in range(2):
b_df.iloc[i,:] = a_df.iloc[0,i*4:(i+1)*4]
Daje mi tylko następujące wyniki
0 1 2 3
0 1 2 3 4
1 NaN NaN NaN NaN
Ale kiedy się zmieniłem b_df.iloc[i,:]
na b_df.iloc[i][:]
. Wynik jest poprawny, jak poniżej, i tego właśnie chcę
0 1 2 3
0 1 2 3 4
1 5 6 7 8
Czy ktoś mógłby mi wyjaśnić, jaka jest różnica między .iloc[i,:]
i .iloc[i][:]
, i dlaczego .iloc[i][:]
działał w moim przykładzie powyżej, ale nie.iloc[i,:]
b_df.iloc[1] = a_df.iloc[0, 4:8]
przypisuje serię z indeksem[4, 5, 6, 7]
do serii z indeksem[0, 1, 2, 3]
. Nie ma nakładania się, więcNaN
s są przypisywane do wszystkich elementów. Do tego momentu ma to dla mnie sens. Ale podobnie jak ty nie jestem pewien, dlaczegob_df.iloc[1][:] = ...
zachowuje się inaczej - sprawdzanie obiektówb_df.iloc[1]
ib_df.iloc[1][:]
nie ujawnia żadnej różnicy między wskaźnikami. Domyślam się, że przypisanie bezpośrednio do copy ([:]
) jest traktowane przez Pandas jako szczególny przypadek, co powoduje, że ignoruje on indeks cesjonariusza i powoduje tę rozbieżność.Odpowiedzi:
Istnieje bardzo, bardzo duża różnica pomiędzy,
series.iloc[:]
aseries[:]
przy cofaniu.(i)loc
zawsze sprawdza, aby upewnić się, że cokolwiek przypisujesz z, pasuje do indeksu cesjonariusza. Tymczasem[:]
składnia przypisuje do podstawowej tablicy NumPy, pomijając wyrównanie indeksu.Teraz, gdy rozumiesz różnicę, spójrzmy na to, co dzieje się w kodzie. Po prostu wydrukuj RHS swoich pętli, aby zobaczyć, co przypisujesz:
Podczas przypisywania do
b_df.iloc[i, :]
w drugiej iteracji indeksy są różne, więc nic nie jest przypisywane i widoczne są tylko NaN. Jednak zmianab_df.iloc[i, :]
nab_df.iloc[i][:]
oznaczać będzie przypisanie do podstawowej tablicy NumPy, więc wyrównanie indeksowania zostanie pominięte. Ta operacja jest lepiej wyrażona jakoWarto również wspomnieć, że jest to forma przypisania łańcuchowego, co nie jest dobrą rzeczą , a także sprawia, że kod jest trudniejszy do odczytania i zrozumienia.
źródło
[:]
składnia przypisuje do podstawowej tablicy NumPy”?Różnica polega na tym, że w pierwszym przypadku interpreter języka Python wykonał kod jako:
gdzie wartość byłaby prawą stroną równania. Podczas gdy w drugim przypadku interpreter języka Python wykonał kod jako:
gdzie znowu wartość byłaby prawą stroną równania.
W każdym z tych dwóch przypadków inna metoda byłaby wywoływana wewnątrz setitem z powodu różnicy w klawiszach (i, plasterek (Brak)) i plasterek (Brak) Dlatego mamy inne zachowanie.
źródło
b_df.iloc[i]
ib_df.iloc[i][:]
mają te same wskaźniki. Dlaczego możesz przypisać serię z niepasującym indeksem do jednego, ale nie do drugiego?Różnica między
.iloc[i,:]
i.iloc[i][:]
W przypadku
.iloc[i,:]
, gdy uzyskujesz bezpośredni dostęp do konkretnej opcjiDataFrame
, wybierając wszystkie (:
) kolumny zi
tego rzędu. O ile wiem, równoważne jest pozostawienie drugiego wymiaru nieokreślonego (.iloc[i]
).W przypadku
.iloc[i][:]
wykonujesz 2 łańcuchu operacji. Tak więc na wynik.iloc[i]
będzie miał wpływ[:]
. Używanie tego do ustawiania wartości jest odradzane przez samą Pandas tutaj z ostrzeżeniem, więc nie powinieneś jej używać:Jak wspomniał @Scott w komentarzach OP, wyrównanie danych jest nieodłączne , więc indeksy po prawej stronie
=
nie zostaną uwzględnione, jeśli nie będą obecne po lewej stronie. DlategoNaN
w drugim rzędzie są wartości.Aby pozostawić sprawę jasną, możesz wykonać następujące czynności:
Lub możesz przekonwertować na
list
zamiast używaćreset_index
:źródło