2016-11-16 83 views
5

我有一個很大的數值數據集(〜700行,350,000列,以R中的data.table讀入)包含一些NA,我想用列方法代替儘可能。我發現以前的帖子用0代替NA,但是當我修改解決方案而不是輸入列的意思時,我得到j,即列號。似乎我必須錯過顯而易見的東西......關於如何計算列意味着使用這種方法的任何建議?最簡單的方法來推算列意味着大數據

Fastest way to replace NAs in a large data.table

#original code 
f_dowle3 = function(DT) { 
    for(j in seq_len(ncol((DT))) 
     set(DT,which(is.na(DT[[j]])),j,0) 
} 

#modified code 
impute = function(DT) { 
    for(j in 2:ncol(DT)) 
     set(DT,which(is.na(DT[[j]])),j,mean(DT[,j],na.rm = TRUE)) 
} 

test_impute = fread("test_impute.csv") 

test_impute 
    ID snp1 snp2 snp3 snp4 
1: 1 2 1 1 0 
2: 2 2 2 0 0 
3: 3 2 NA 0 NA 
4: 4 2 1 2 0 
5: 5 2 NA 2 0 
6: 6 2 1 1 0 
7: 7 1 1 NA 0 
8: 8 NA 1 0 0 
9: 9 2 2 2 NA 
10: 10 1 1 0 0 


impute(test_impute) 

test_impute 
    ID snp1 snp2 snp3 snp4 
1: 1 2 1 1 0 
2: 2 2 2 0 0 
3: 3 2 3 0 5 
4: 4 2 1 2 0 
5: 5 2 3 2 0 
6: 6 2 1 1 0 
7: 7 1 1 4 0 
8: 8 2 1 0 0 
9: 9 2 2 2 5 
10: 10 1 1 0 0 

回答

6

不能使用dt1[, j]從數據表搶列。

dt1[, 1] 
# [1] 1 
dt1[, 2342] 
# [1] 2342 

變化DT[, j]DT[[j]]修復。

首先,一些數據:

set.seed(47) 
n = 10 
ncol = 10 
dt1 = data.table(replicate(ncol, expr = { 
    ifelse(runif(n) < 0.2, NA_real_, rpois(n, 10)) 
})) 

impute1 = function(DT) { 
    for (j in 2:ncol(DT)) 
     set(DT, which(is.na(DT[[j]])), j, mean(DT[[j]], na.rm = TRUE)) 
} 

dt1 
#  V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 
# 1: 6 11 10 7 13 10 12 8 13 12 
# 2: 10 8 NA 7 16 10 10 8 5 5 
# 3: 14 7 9 9 NA 13 9 NA 10 NA 
# 4: 4 4 13 10 7 10 14 8 13 15 
# 5: 7 NA 8 NA 12 NA 15 10 11 8 
# 6: 6 9 7 15 NA 5 12 15 10 5 
# 7: 4 9 5 NA 10 12 9 8 12 14 
# 8: 12 8 NA 9 7 NA 11 4 8 11 
# 9: 8 10 12 14 10 NA 11 9 10 10 
# 10: 7 6 NA 13 8 14 11 6 10 NA 
impute1(dt1) 
dt1 
#  V1 V2  V3 V4  V5  V6 V7  V8 V9 V10 
# 1: 6 11 10.000000 7.0 13.000 10.00000 12 8.000000 13 12 
# 2: 10 8 9.142857 7.0 16.000 10.00000 10 8.000000 5 5 
# 3: 14 7 9.000000 9.0 10.375 13.00000 9 8.444444 10 10 
# 4: 4 4 13.000000 10.0 7.000 10.00000 14 8.000000 13 15 
# 5: 7 8 8.000000 10.5 12.000 10.57143 15 10.000000 11 8 
# 6: 6 9 7.000000 15.0 10.375 5.00000 12 15.000000 10 5 
# 7: 4 9 5.000000 10.5 10.000 12.00000 9 8.000000 12 14 
# 8: 12 8 9.142857 9.0 7.000 10.57143 11 4.000000 8 11 
# 9: 8 10 12.000000 14.0 10.000 10.57143 11 9.000000 10 10 
# 10: 7 6 9.142857 13.0 8.000 14.00000 11 6.000000 10 10 

另一種選擇是預先計算的柱裝置。 colMeans速度非常快,所以整體速度可能會更快,尤其是對於具有儘可能多的列。

impute2 = function(DT) { 
    means = colMeans(DT, na.rm = T) 
    for (j in 2:ncol(DT)) 
     set(DT, which(is.na(DT[[j]])), j, means[j]) 
} 
+0

非常感謝你!這解決了這兩個方法的工作!我會用後者,因爲它可能是一個更快的選項。 – bdarst

+2

Fyi回答你的答案的第一部分,在切換選項之後,可以改變行爲。請參閱新聞中的第3條1.9.7:https://github.com/Rdatatable/data.table/blob/master/NEWS.md所以我可以做'options(datatable.WhenJisSymbolThenCallingScope = TRUE); dt [,1]'子集到第一列。 – Frank

+1

哇,這是一個選項名稱的地獄。我確切知道它做了什麼。 – Gregor

1

如果您不想創建自己的函數,還可以使用其他插補程序包。

例如imputeTS

library(imputeTS) 
solution <- na.mean(yourDataframe) 

其他包,比如小鼠也有類似的選項。

猜你必須測試哪一個是最快的。 可能是Gregors最後的解決方案已經是最快的了。