Considere el marco de datos df
df = pd.DataFrame(dict(A=[1, 2], B=['X', 'Y']))
df
A B
0 1 X
1 2 Y
Si me desplazo axis=0
(el valor predeterminado)
df.shift()
A B
0 NaN NaN
1 1.0 X
Empuja todas las filas hacia abajo una fila como se esperaba.
Pero cuando cambio axis=1
df.shift(axis=1)
A B
0 NaN NaN
1 NaN NaN
Todo es nulo cuando esperaba
A B
0 NaN 1
1 NaN 2
Entiendo por qué sucedió esto. Para axis=0
, Pandas está operando columna por columna donde cada columna es una sola dtype
y al cambiar, hay un protocolo claro sobre cómo lidiar con el NaN
valor introducido al principio o al final. Pero cuando axis=1
avanzamos introducimos una posible ambigüedad de dtype
una columna a la siguiente. En este caso, trato de forzar int64
una object
columna y Pandas decide simplemente anular los valores.
Esto se vuelve más problemático cuando dtypes
son int64
yfloat64
df = pd.DataFrame(dict(A=[1, 2], B=[1., 2.]))
df
A B
0 1 1.0
1 2 2.0
Y sucede lo mismo
df.shift(axis=1)
A B
0 NaN NaN
1 NaN NaN
Mi pregunta
¿Cuáles son buenas opciones para crear un marco de datos que se desplaza axis=1
en el que el resultado ha cambiado los valores y los tipos de letra?
Para el caso int64
/ float64
el resultado se vería así:
df_shifted
A B
0 NaN 1
1 NaN 2
y
df_shifted.dtypes
A object
B int64
dtype: object
Un ejemplo mas completo
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
Debería verse así
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 esto en su lugar y veadf = pd.DataFrame(dict(A=[1, 2], B=[3., 4.], C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))
Respuestas:
Resulta que Pandas está cambiando sobre bloques de similares
dtypes
Definir
df
comoDesplazará los enteros a la siguiente columna entera, los flotantes a la siguiente columna flotante y los objetos a la siguiente columna de objetos.
No sé si es una buena idea, pero eso es lo que está sucediendo.
Enfoques
astype(object)
primerotranspose
Lo haremos
object
itertuples
Aunque probablemente haría esto
fuente
str
tipo, entonces funciona correctamente, si haces lo mismo en este dfdf = pd.DataFrame(dict(C=['X', 'Y'], D=[5., 6.], E=[7, 8], F=['W', 'Z']))
, cambia la'XY'
columna por completo'F'
, esto definitivamente es incorrecto para mí, mi versión de pandas es0.24.2
, no debería hacerdtype
promoción y no cambiar las columnas en tal una maneraIntenté usar un
numpy
método. El método funciona siempre que mantenga sus datos en una matriz numpy:Pero cuando llama al
DataFrame
constructor, todas las columnas se conviertenobject
aunque los valores en la matriz sonfloat, int, object
:fuente