簡體   English   中英

R,bit64,計算data.table中的行均值和標准差的問題

[英]R, bit64, problems calculating row mean and standard deviation in data.table

我試圖使用更大的數字,超過2 ^ 32。 雖然我也在使用data.table和fread,但我不相信這個問題與它們有關。 我可以在不改變data.table或使用fread的情況下打開和關閉他們的症狀。 我的症狀是,當我期待正指數1e + 3到1e + 17時,我得到的報告平均值為4.1e-302

使用bit64包和與integer64相關的函數時,問題始終出現。 在“常規大小的數據和R”中,事情對我有用,但我在這個包中沒有正確表達。 請參閱下面的代碼和數據。

我在MacBook Pro上,16GB,i7(已更新)。

我重新啟動了我的R會話並清除了工作區,但問題仍然存在。

請恭喜,我很感激投入。 我假設它必須使用庫bit64。

我看過的鏈接包括bit64 doc

由於fread()內存泄漏導致類似症狀的問題,但我想我已經消除了

這是我的輸入數據

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 

我的代碼,使用此示例數據

# 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

......現在問題開始了

# -------------------------------------------------------------------
# ---- 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

常規數據上的常規大小R,仍然使用fread()讀入的數據到data.table() - WORKS

# -------------------------------------------------------------------
# ---- 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

作為大多數讀者的簡短推薦:除非你有特定的理由使用64位整數,否則請使用'double'而不是'integer64'。 'double'是R內部數據類型,而'integer64'是包擴展數據類型,它表示為具有類屬性'integer64'的'double'向量,即每個元素64位被知道的代碼解釋為64位整數關於這堂課。 不幸的是,許多核心R函數不知道'integer64',這很容易導致錯誤的結果。 因此強迫'加倍'

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

會給出一些預期的結果

> 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

雖然不完全是你所期望的,但也沒有看到圓潤的差異

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

也沒有看到沒有根據的差異

> 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

好的,我們假設你真的想要 integer64,因為你的最大數字超出了整數精度2 ^ 52的雙精度數。 然后你的問題開始於'apply'不知道integer64並且實際上破壞'integer64'類屬性的事實:

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

它實際上兩次破壞'integer64'類屬性,一次是在准備輸入時,一次是在后處理輸出時。 我們可以解決這個問題

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

現在結果看起來很合理

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

但仍然不是你所期望的

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

由於浮動平均值,小的差異(-1)是由於舍入

> b[1]
[1] 995.6667

而你假設

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

而mean.integer64 脅迫 (截斷)來integer64。 mean.integer64的這種行為是值得商榷的,但至少是一致的:

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

四舍五入的主題清楚地表明,實現sd.integer64會更有爭議。 應該返回integer64還是double?

關於更大的差異,我們不清楚你期望的理由是什么:取你的第七排並減去它的最小值

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

給出“double”精確處理整數的范圍內的數字

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

平均這些並與您的期望進行比較仍然會產生差異,而不是通過四舍五入來解釋

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM