2016-09-24 2 views
3

J'essaie de travailler avec de plus grands nombres, plus de 2^32. Bien que j'utilise aussi data.table et fread, je ne crois pas que le problème soit lié à eux. Je peux allumer et éteindre leurs symptômes sans changer data.table ou avoir utilisé fread. Mes symptômes sont que j'obtiens une moyenne rapportée de 4.1e-302 quand je m'attends à un exposant positif 1e + 3 à 1e + 17R, bit64, problèmes calculant la moyenne de ligne et l'écart-type dans data.table

Le problème apparaît de manière cohérente lors de l'utilisation du paquetage bit64 et des fonctions liées à integer64. Les choses fonctionnent pour moi dans "les données de taille normale et R" mais je n'exprime pas les choses correctement dans ce paquet. Voir mon code et mes données ci-dessous.

Je suis sur un MacBook Pro, 16 Go, i7 (mis à jour).

J'ai redémarré ma session R et effacé l'espace de travail, mais le problème persiste.

S'il vous plaît veuillez aviser, j'apprécie l'entrée. Je suppose qu'il doit utiliser la bibliothèque, bit64.

Liens Je regardé inclus bit64 doc

An issue that had similar symptoms caused by an fread() memory leak, but I think I eliminated

Voici mes données d'entrée

var1,var2,var3,var4,var5,var6,expected_row_mean,expected_row_stddev 
1000 ,993 ,987 ,1005 ,986 ,1003 ,996 ,8 
100000 ,101040 ,97901 ,100318 ,96914 ,97451 ,98937 ,1722 
10000000 ,9972997 ,9602778 ,9160554 ,8843583 ,8688500 ,9378069 ,565637 
1000000000 ,1013849241 ,973896894 ,990440721 ,1030267777 ,1032689982 ,1006857436 ,23096234 
100000000000 ,103171209097 ,103660949260 ,102360301140 ,103662297222 ,106399064194 ,103208970152 ,2078732545 
10000000000000 ,9557954451905 ,9241065464713 ,9357562691674 ,9376495364909 ,9014072235909 ,9424525034852 ,334034298683 
1000000000000000 ,985333546044881 ,994067361457872 ,1034392968759970 ,1057553099903410 ,1018695335152490 ,1015007051886440 ,27363415718203 
100000000000000000 ,98733768902499600 ,103316759127969000 ,108062824583319000 ,111332326225036000 ,108671041505404000 ,105019453390705000 ,5100048567944390 

Mon code, en collaboration avec cet échantillon de données

# file: problem_bit64.R 
# OBJECTIVE: Using larger numbers, I want to calculate a row mean and row standard deviation 
# ERROR: I don't know what I am doing wrong to get such errors, seems bit64 related 
# PRIORITY: BLOCKED (do this in Python instead?) 
# reported Sat 9/24/2016 by Greg 

# sample data: 
# each row is 100 times larger on average, for 8 rows, starting with 1,000 
# for the vars within a row, there is 10% uniform random variation. B2 = ROUND(A2+A2*0.1*(RAND()-0.5),0)  

# Install development version of data.table --> for fwrite() 
install.packages("data.table", repos = "https://Rdatatable.github.io/data.table", type = "source") 
require(data.table) 
require(bit64) 
.Machine$integer.max # 2147483647  Is this an issue ? 
.Machine$double.xmax # 1.797693e+308 I assume not 

# ------------------------------------------------------------------- 
# ---- read in and basic info that works 
csv_in <- "problem_bit64.csv" 
dt <- fread(csv_in) 
dim(dt)    # 6 8 
lapply(dt, class)  # "integer64" for all 8 
names(dt) # "var1" "var2" "var3" "var4" "var5" "var6" "expected_row_mean" "expected_row_stddev" 
dtin <- dt[, 1:6, with=FALSE] # just save the 6 input columns 

... maintenant les problèmes sta rt

# ------------------------------------------------------------------- 
# ---- CALCULATION PROBLEMS START HERE 
# ---- for each row, I want to calculate the mean and standard deviation 
a <- apply(dtin, 1, mean.integer64); a # get 8 values like 4.9e-321 
b <- apply(dtin, 2, mean.integer64); b # get 6 values like 8.0e-308 

# ---- try secondary variations that do not work 
c <- apply(dtin, 1, mean); c    # get 8 values like 4.9e-321 
c <- apply(dtin, 1, mean.integer64); c # same result 
c <- apply(dtin, 1, function(x) mean(x)); c   # same 
c <- apply(dtin, 1, function(x) sum(x)/length(x)); c # same results as mean(x) 

##### I don't see any sd.integer64  # FEATURE REQUEST, Z-TRANSFORM IS COMMON 
c <- apply(dtin, 1, function(x) sd(x)); c   # unrealistic values - see expected 

taille régulière R sur des données régulières, toujours en utilisant les données lues avec fread() dans un data.table() - TRAVAUX

# ------------------------------------------------------------------- 
# ---- delete big numbers, and try regular stuff - WHICH WORKS 
dtin2 <- dtin[ 1:3, ] # just up to about 10 million (SAME DATA, SAME FREAD, SAME DATA.TABLE) 
dtin2[ , var1 := as.integer(var1) ] # I know there are fancier ways to do this 
dtin2[ , var2 := as.integer(var2) ] # but I want things to work before getting fancy. 
dtin2[ , var3 := as.integer(var3) ] 
dtin2[ , var4 := as.integer(var4) ] 
dtin2[ , var5 := as.integer(var5) ] 
dtin2[ , var6 := as.integer(var6) ] 
lapply(dtin2, class) # validation 

c <- apply(dtin2, 1, mean); c # get 3 row values AS EXPECTED (matching expected columns) 
c <- apply(dtin2, 1, function(x) mean(x)); c   # CORRECT 
c <- apply(dtin2, 1, function(x) sum(x)/length(x)); c # same results as mean(x) 

c <- apply(dtin2, 1, sd); c    # get 3 row values AS EXPECTED (matching expected columns) 
c <- apply(dtin2, 1, function(x) sd(x)); c   # CORRECT 
+0

Avez-vous essayé d'autres alternatives aux grands nombres, comme 'Brobdingnag'? Ils ne peuvent pas bien jouer avec data.table, mais vous n'utilisez pas vraiment la fonction spéciale data.table. Vous pouvez même utiliser fread avec 'data.table = FALSE' pour obtenir un bloc de données. – dracodoc

Répondre

1

Comme une recommandation à court et premier à la plupart des lecteurs : utilisez 'double' au lieu de 'integer64' sauf si vous avez une raison spécifique d'utiliser des entiers 64 bits. 'double' est un type de données interne R, tandis que 'integer64' est un type de données d'extension de paquet, représenté comme un vecteur 'double' avec un attribut de classe 'integer64', c'est-à-dire que chaque élément est interprété comme un entier à propos de cette classe. Malheureusement, de nombreuses fonctions du noyau R ne connaissent pas 'integer64', ce qui conduit facilement à de mauvais résultats. Par conséquent contraindre à « double »

dtind <- dtin 
for (i in seq_along(dtind)) 
    dtind[[i]] <- as.double(dtind[[i]]) 
b <- apply(dtind, 1, mean) 

donnera le peu attendu résultat

> b 
[1] 9.956667e+02 9.893733e+04 9.378069e+06 1.006857e+09 1.032090e+11 9.424525e+12 1.015007e+15 1.050195e+17 

mais pas exactement ce que vous attendiez, ni regarder les différences arrondies

> b - dt$expected_row_mean 
integer64 
[1] -1 0 -1 -1 0 -1 -3 -392 

ni regarder la différences non arrondies

> b - as.double(dt$expected_row_mean) 
[1] -0.3333333 0.3333333 -0.3333333 -0.1666666 0.1666718 -0.3339844 -2.8750000 -384.0000000 
Warnmeldung: 
In as.double.integer64(dt$expected_row_mean) : 
    integer precision lost while converting to double 

OK, supposons que vous vraiment voulez nombre entier64 parce que vos plus grands nombres sont au-delà de la précision entière 2^52 de doubles.Ensuite, votre problème commence par le fait que « appliquer » ne sait pas integer64 et détruit en fait l'attribut de classe « integer64 »:

> apply(dtin, 1, is.integer64) 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

Il détruit en fait l'attribut de classe « integer64 » deux fois, une fois dans la préparation du entrées et une fois lors du post-traitement des sorties. Nous pouvons résoudre ce problème en

c <- apply(dtin, 1, function(x){ 
    oldClass(x) <- "integer64" # fix 
    mean(x) # note that this dispatches to mean.integer64 
}) 
oldClass(c) <- "integer64" # fix again 

Maintenant, le résultat semble raisonnable

> c 
integer64 
[1] 995    98937    9378068   1006857435   103208970152  9424525034851  1015007051886437 105019453390704600 

mais toujours pas ce que vous attendiez

> c - dt$expected_row_mean 
integer64 
[1] -1 0 -1 -1 0 -1 -3 -400 

Les petites différences (-1) sont dues à l'arrondissement, depuis la moyenne flottante

> b[1] 
[1] 995.6667 

et vous assumez

> dt$expected_row_mean[1] 
integer64 
[1] 996 

tout mean.integer64 (tronque contraint) à integer64. Ce comportement de mean.integer64 est discutable, mais, au moins cohérente:

x <- seq(0, 1, 0.25) 
> data.frame(x=x, y=as.integer64(0) + x) 
    x y 
1 0.00 0 
2 0.25 0 
3 0.50 0 
4 0.75 0 
5 1.00 1 
> mean(as.integer64(0:1)) 
integer64 
[1] 0 

Le sujet de l'arrondissement précise que la mise en œuvre sd.integer64 serait encore plus discutable. Devrait-il retourner integer64 ou double?

En ce qui concerne les plus grandes différences on ne sait pas ce que la raison d'être de votre attente est: prendre la septième ligne de votre table et retranchant son minimum

x <- (unlist(dtin[7,])) 
oldClass(x) <- "integer64" 
y <- min(x) 
z <- as.double(x - y) 

donne des nombres dans une plage où « double » poignées précisément entiers

> log2(z) 
[1] 43.73759  -Inf 42.98975 45.47960 46.03745 44.92326 

moyenne et les comparant à vos attentes donne toujours une différence non expliquée par l'arrondissement

> mean(z) - as.double(dt$expected_row_mean[7] - y) 
[1] -2.832031 
+0

Merci beaucoup pour votre réponse - cela a bien fonctionné. –