Considere o quadro de dados df
df = pd.DataFrame(dict(A=[1, 2], B=['X', 'Y']))
df
A B
0 1 X
1 2 Y
Se eu mudar axis=0
(o padrão)
df.shift()
A B
0 NaN NaN
1 1.0 X
Empurra todas as linhas para baixo uma linha, conforme o esperado.
Mas quando eu mudo axis=1
df.shift(axis=1)
A B
0 NaN NaN
1 NaN NaN
Tudo é nulo quando eu esperava
A B
0 NaN 1
1 NaN 2
Eu entendo por que isso aconteceu. Pois axis=0
, o Pandas está operando coluna por coluna, onde cada coluna é única dtype
e, ao mudar, existe um protocolo claro sobre como lidar com o NaN
valor introduzido no início ou no final. Mas, ao mudar axis=1
, introduzimos a ambiguidade potencial de dtype
uma coluna para a seguinte. Nesse caso, estou tentando forçar int64
uma object
coluna e o Pandas decide apenas anular os valores.
Isso se torna mais problemático quando o dtypes
são int64
efloat64
df = pd.DataFrame(dict(A=[1, 2], B=[1., 2.]))
df
A B
0 1 1.0
1 2 2.0
E a mesma coisa acontece
df.shift(axis=1)
A B
0 NaN NaN
1 NaN NaN
Minha pergunta
Quais são as boas opções para criar um quadro de dados que é deslocado ao longo axis=1
do qual o resultado alterou valores e tipos?
Para o caso int64
/ float64
, o resultado seria semelhante a:
df_shifted
A B
0 NaN 1
1 NaN 2
e
df_shifted.dtypes
A object
B int64
dtype: object
Um exemplo mais abrangente
df = pd.DataFrame(dict(A=[1, 2], B=[1., 2.], C=['X', 'Y'], D=[4., 5.], E=[4, 5]))
df
A B C D E
0 1 1.0 X 4.0 4
1 2 2.0 Y 5.0 5
Deve ficar assim
df_shifted
A B C D E
0 NaN 1 1.0 X 4.0
1 NaN 2 2.0 Y 5.0
df_shifted.dtypes
A object
B int64
C float64
D object
E float64
dtype: object
object
?object
blocks
>. <Use isso em vez disso e vejadf = pd.DataFrame(dict(A=[1, 2], B=[3., 4.], C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))
Respostas:
Acontece que os pandas estão mudando sobre blocos de similares
dtypes
Definir
df
comoEle mudará os números inteiros para a próxima coluna inteira, os flutuadores para a próxima coluna flutuante e os objetos para a próxima coluna de objetos
Não sei se é uma boa ideia, mas é isso que está acontecendo.
Abordagens
astype(object)
primeirotranspose
Vai fazer isso
object
itertuples
Embora eu provavelmente faria isso
fonte
str
tipo, então funciona corretamente, se você faz o mesmo neste df,df = pd.DataFrame(dict(C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))
ele muda a'XY'
coluna para a'F'
coluna, isso é definitivamente errado para mim, minha versão do pandas é0.24.2
: ela deve fazerdtype
promoção e não alterar as colunas em tais um caminhoEu tentei usar um
numpy
método. O método funciona desde que você mantenha seus dados em uma matriz numpy:Mas quando você chama o
DataFrame
construtor, todas as colunas são convertidas em,object
embora os valores na matriz sejamfloat, int, object
:fonte