2016-11-16 20 views
5

Tôi có một tập dữ liệu số lớn (~ 700 hàng, 350.000 cột, đọc dưới dạng dữ liệu.table trong R) chứa một số NA mà tôi muốn thay thế bằng cột có nghĩa là nhanh chóng càng tốt. Tôi tìm thấy một bài trước đó thay thế NA với 0, nhưng khi tôi sửa đổi các giải pháp để thay vào đó cột đầu vào có nghĩa là, tôi nhận được j, số cột. Có vẻ như tôi phải thiếu một cái gì đó hiển nhiên ... Bất kỳ gợi ý về cách tính cột có nghĩa là sử dụng phương pháp này?Cách nhanh nhất để bóp cột có nghĩa là với dữ liệu lớn

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 

Trả lời

6

Bạn không thể sử dụng dt1[, j] để lấy một cột từ một bảng dữ liệu.

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

Thay đổi DT[, j] thành DT[[j]] để khắc phục.

Đầu tiên một số dữ liệu:

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 

Một lựa chọn khác sẽ được tính toán trước cột nghĩa. colMeans là khá nhanh, vì vậy điều này có thể nhanh hơn tổng thể, đặc biệt là với nhiều cột như bạn có.

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

Cảm ơn bạn rất nhiều !! Điều đó cố định nó và cả hai phương pháp này hoạt động! Tôi sẽ sử dụng sau vì nó có thể là một lựa chọn nhanh hơn. – bdarst

+2

Fyi lại phần đầu tiên của câu trả lời của bạn, trong devel sau khi toggling một tùy chọn, hành vi đó có thể được thay đổi. Xem mục 3 trong tin tức cho 1.9.7: https://github.com/Rdatatable/data.table/blob/master/NEWS.md Vì vậy, tôi có thể làm 'tùy chọn (datatable.WhenJisSymbolThenCallingScope = TRUE); dt [, 1] 'để tập hợp con col đầu tiên. – Frank

+1

Wow, đó là một tên địa ngục. Tôi biết chính xác những gì nó làm. – Gregor

1

Nếu bạn không muốn tạo chức năng riêng, bạn cũng có thể sử dụng gói mô phỏng khác.

Ví dụ imputeTS:

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

gói khác như chuột cũng có các tùy chọn tương tự.

Đoán bạn sẽ phải thử nghiệm, cái nào là nhanh nhất. Có thể Gregors giải pháp cuối cùng đã là nhanh nhất.

Các vấn đề liên quan