Estou tão confuso com diferentes métodos de indexação usando iloc
em pandas.
Digamos que estou tentando converter um Dataframe 1-d para um Dataframe 2-d. Primeiro, tenho o seguinte Dataframe 1-d
a_array = [1,2,3,4,5,6,7,8]
a_df = pd.DataFrame(a_array).T
E eu vou converter isso em um Dataframe 2D com o tamanho de 2x4
. Começo predefinindo o Dataframe 2-d da seguinte maneira:
b_df = pd.DataFrame(columns=range(4),index=range(2))
Então eu uso o loop for para me ajudar a converter a_df
(1-d) emb_df
(2-d) com o seguinte código
for i in range(2):
b_df.iloc[i,:] = a_df.iloc[0,i*4:(i+1)*4]
Apenas me fornece os seguintes resultados
0 1 2 3
0 1 2 3 4
1 NaN NaN NaN NaN
Mas quando mudei b_df.iloc[i,:]
parab_df.iloc[i][:]
. O resultado está correto como o seguinte, que é o que eu quero
0 1 2 3
0 1 2 3 4
1 5 6 7 8
Alguém poderia me explicar qual é a diferença entre .iloc[i,:]
e .iloc[i][:]
é e por que .iloc[i][:]
funcionou no meu exemplo acima, mas não.iloc[i,:]
b_df.iloc[1] = a_df.iloc[0, 4:8]
atribui uma série com índice[4, 5, 6, 7]
a uma série com índice[0, 1, 2, 3]
. Não há sobreposição, portanto,NaN
é atribuído a todos os elementos. Até este ponto, faz sentido para mim. Mas, como você, não sei por queb_df.iloc[1][:] = ...
se comporta de maneira diferente - inspecionando os objetosb_df.iloc[1]
eb_df.iloc[1][:]
não revela diferença entre os índices. Meu melhor palpite seria que atribuir diretamente a uma cópia ([:]
) é tratado como um caso especial pelo Pandas, o que faz com que ignore o índice do responsável e crie essa discrepância.Respostas:
Há uma diferença muito, muito grande entre
series.iloc[:]
eseries[:]
, ao atribuir de volta.(i)loc
sempre verifica se o que você está atribuindo corresponde ao índice do responsável. Enquanto isso, a[:]
sintaxe é atribuída à matriz NumPy subjacente, ignorando o alinhamento do índice.Agora que você entende a diferença, vejamos o que acontece no seu código. Basta imprimir o RHS dos seus loops para ver o que você está atribuindo:
Ao atribuir a
b_df.iloc[i, :]
na segunda iteração, os índices são diferentes, portanto nada é atribuído e você vê apenas NaNs. No entanto, alterarb_df.iloc[i, :]
parab_df.iloc[i][:]
significa que você atribui à matriz NumPy subjacente, portanto, o alinhamento da indexação é ignorado. Esta operação é melhor expressa comoTambém vale a pena mencionar que esta é uma forma de atribuição encadeada, o que não é uma coisa boa e também torna seu código mais difícil de ler e entender.
fonte
[:]
sintaxe atribui à matriz NumPy subjacente"?A diferença é que, no primeiro caso, o interpretador Python executou o código como:
onde o valor seria o lado direito da equação. Enquanto no segundo caso, o interpretador Python executou o código como:
onde novamente o valor seria o lado direito da equação.
Em cada um desses dois casos, um método diferente seria chamado dentro do setitem devido à diferença nas chaves (i, fatia (Nenhuma)) e fatia (Nenhuma). Portanto, temos um comportamento diferente.
fonte
b_df.iloc[i]
eb_df.iloc[i][:]
ter os mesmos índices. Por que você pode atribuir uma série com índice não correspondente a uma, mas não a outra?A diferença entre
.iloc[i,:]
e.iloc[i][:]
No caso de
.iloc[i,:]
você estar acessando diretamente uma posição específica doDataFrame
, selecionando todas as:
colunas dai
linha th. Até onde eu sei, é equivalente deixar a 2ª dimensão não especificada (.iloc[i]
).No caso de
.iloc[i][:]
você estar executando duas operações encadeadas. Portanto, o resultado de.iloc[i]
será afetado por[:]
. Usar isso para definir valores é desencorajado pelo próprio Pandas aqui com um aviso, portanto você não deve usá-lo:Como o @Scott mencionado nos comentários do OP, o alinhamento de dados é intrínseco , portanto, os índices no lado direito do
=
não serão incluídos se não estiverem presentes no lado esquerdo. É por isso que existemNaN
valores na 2ª linha.Portanto, para deixar as coisas claras, você pode fazer o seguinte:
Ou você pode converter para em
list
vez de usarreset_index
:fonte