recommendation - Data.table de la R ¿Truncando Bits?
title seo length (1)
Actualización: la función de redondeo predeterminada se ha eliminado en la versión de desarrollo actual de data.table (v1.9.7) . Vea las instrucciones de instalación para la versión de desarrollo here .
Esto también significa que usted es responsable de comprender las limitaciones para representar números de punto flotante y tratar con ellos.
data.table ha existido durante mucho tiempo. Solíamos lidiar con las limitaciones en las representaciones de punto flotante usando un umbral (como lo hace la base R, por ejemplo, all.equal
). Sin embargo, simplemente no funciona, ya que debe ser adaptable según el tamaño de los números comparados. Esta serie de artículos es una excelente lectura sobre este tema y otros problemas potenciales.
Este es un problema recurrente porque a) la gente no se da cuenta de las limitaciones, o b) el umbral no ayudó realmente a su problema, lo que significa que la gente seguía preguntando aquí o publicando en la página del proyecto.
Mientras reimplementamos el orden de data.table para el ordenamiento rápido de radix, aprovechamos la oportunidad para proporcionar una forma alternativa de solucionar el problema y proporcionar una salida si resulta indeseable (exportar setNumericRounding
). Con el problema # 1642, el ordenamiento probablemente no necesite redondear los dobles (pero no es tan simple, ya que el orden afecta directamente a los subconjuntos basados en búsquedas binarias).
El problema real aquí es agrupar en números de punto flotante , aún peor son los números como en su caso. Esa es solo una mala elección, en mi humilde opinión.
Puedo pensar en dos maneras de avanzar:
Al agrupar en columnas que realmente se duplican (en R, 1 es el doble en lugar de 1L, y esos casos no tienen problemas), brindamos una advertencia de que los últimos 2 bytes están redondeados y que la gente debería leer
?setNumericRounding
. Y también sugiero usarbit64::integer64
.Elimine la funcionalidad de permitir operaciones de agrupación en valores realmente dobles o obligarlos a corregir la precisión en ciertos dígitos antes de continuar. No puedo pensar en una razón válida por la que uno quisiera agrupar por números de punto flotante realmente (me encantaría saber de las personas que lo hacen).
Lo que es muy poco probable que ocurra es volver a las verificaciones basadas en umbrales para identificar qué dobles deben pertenecer al mismo grupo.
Solo para que la Q siga respondiendo, use setNumericRounding(0L)
.
Así que soy un gran fanático de los datos en R. Lo uso casi todo el tiempo, pero me he encontrado con una situación en la que no funcionará para mí en absoluto. Tengo un paquete (interno a mi compañía) que usa el double
de R para almacenar el valor de un entero de 64 bits sin signo cuya secuencia de bits corresponde a una codificación elegante. Este paquete funciona muy bien en todas partes excepto data.table. Descubrí que si agrego en una columna de estos datos, pierdo una gran cantidad de mis valores únicos. Mi única suposición aquí es que data.table
está truncando bits en algún tipo de extraña double
optimización.
¿Alguien puede confirmar que este es el caso? ¿Es esto simplemente un error?
A continuación vea una reproducción del problema y una comparación con el paquete que actualmente debo usar pero que quiero evitar con una pasión ( dplyr
).
temp <- structure(list(obscure_math = c(6.95476896592629e-309, 6.95476863436446e-309,
6.95476743245288e-309, 6.95476942182375e-309, 6.95477149408563e-309,
6.95477132830476e-309, 6.95477132830476e-309, 6.95477149408562e-309,
6.95477174275702e-309, 6.95476880014538e-309, 6.95476896592647e-309,
6.95476896592647e-309, 6.95476900737172e-309, 6.95476900737172e-309,
6.95476946326899e-309, 6.95476958760468e-309, 6.95476958760468e-309,
6.95477020928318e-309, 6.95477124541406e-309, 6.95476859291965e-309,
6.95476875870014e-309, 6.95476904881676e-309, 6.95476904881676e-309,
6.95476904881676e-309, 6.95476909026199e-309, 6.95476909026199e-309,
6.95476909026199e-309, 6.95476909026199e-309, 6.9547691317072e-309,
6.9547691317072e-309, 6.9547691317072e-309, 6.9547691317072e-309,
6.9547691317072e-309, 6.9547691317072e-309, 6.9547691317072e-309,
6.9547691317072e-309, 6.9547691317072e-309, 6.9547691317072e-309,
6.9547691317072e-309, 6.9547691317072e-309, 6.95477211576406e-309,
6.95476880014538e-309, 6.95476880014538e-309, 6.95476880014538e-309,
6.95476892448104e-309, 6.95476880014538e-309, 6.95476892448105e-309,
6.9547689659263e-309, 6.95476913170719e-309, 6.95476933893334e-309
)), .Names = "obscure_math", class = c("data.table", "data.frame"), row.names = c(NA,
-50L))
dt_collapsed <- temp[, .(count=.N), by=obscure_math]
nrow(dt_collapsed) == length(unique(temp$obscure_math))
setDF(temp)
dplyr_collapsed <- temp %>% group_by(obscure_math) %>% summarise(count=n())
nrow(dplyr_collapsed) == length(unique(temp$obscure_math))