type dtypes dtype data columns column change cast astype python numpy casting

python - dtypes - Numpy casting float32 a float64



python dataframe astype (1)

Quiero realizar algunas operaciones estándar en matrices numpy float32 en python 3, sin embargo, estoy viendo un comportamiento extraño al trabajar con numpy sum() . Aquí hay una sesión de ejemplo:

Python 3.6.1 |Anaconda 4.4.0 (x86_64)| (default, May 11 2017, 13:04:09) [GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)] on darwin import numpy as np np.__version__ Out[3]: ''1.12.1'' a = np.ones(10).astype(np.float32) np.sum(a).dtype Out[5]: dtype(''float32'') (np.sum(a)+1).dtype Out[6]: dtype(''float64'') (np.sum(a)+1.).dtype Out[7]: dtype(''float64'') (a+1).dtype Out[8]: dtype(''float32'')

¿Alguna razón por la que agregar un escalar al resultado de una suma (que parece tener el dtype de float32 ) lo devolvería a float64 ? Para ser claros, sé que puedo convertir explícitamente el escalar a float32 , sin embargo, como muestra la última línea, numpy aún respeta float32 cuando agrega un escalar a una matriz. ¿Alguna explicación o sugerencia de cómo mantener las cosas como float32 sin conversión explícita?


El resultado de np.sum(a) es un escalar NumPy, en lugar de una matriz. Las operaciones que involucran solo escalares utilizan reglas de conversión diferentes de las operaciones que involucran matrices NumPy (de dimensión positiva), descritas en los documentos para numpy.result_type .

Cuando una operación involucra solo escalares (incluidas las matrices de 0 dimensiones), el tipo de resultado se determina únicamente por los dtypes de entrada. Lo mismo es cierto para las operaciones que involucran solo arreglos (de dimensiones positivas).

Sin embargo, cuando se mezclan escalares y matrices (de dimensiones positivas), en lugar de utilizar los dítopes reales de los escalares, NumPy examina los valores de los escalares para ver si un tipo de letra "más pequeño" puede contenerlos, y luego usa ese tipo para el tipo promoción. (Las matrices no pasan por este proceso, incluso si sus valores caben en un tipo más pequeño).

Así,

np.sum(a)+1

es una operación escalar, convirtiendo 1 a un escalar NumPy de dtype int_ (ya sea int32 o int64 dependiendo del tamaño de una C larga) y luego realizando una promoción basada en los dtypes float32 e int32 / int64, pero

a+1

implica una matriz, por lo que el tipo de 1 se trata como int8 para fines de promoción.

Como un float32 no puede contener todos los valores de dtype int32 (o int64), NumPy se actualiza a float64 para la primera promoción. (float64 no puede contener todos los valores de dtype int64, pero NumPy no promocionará numpy.longdouble para esto.) Como float32 puede contener todos los valores de dtype int8, NumPy se queda con float32 para la segunda promoción.

Si usa un número mayor que 1, entonces no cabe en un int8:

In [16]: (a+1).dtype Out[16]: dtype(''float32'') In [17]: (a+1000000000).dtype Out[17]: dtype(''float64'')

puedes ver diferentes comportamientos de promoción.