r - একটি বৃহৎ data.table মধ্যে NAs প্রতিস্থাপন দ্রুততম উপায়




performance dataframe (6)

আমার কাছে একটি বৃহৎ data.table , অনেকগুলি অনুপস্থিত মান ~ 200 ক সারি এবং 200 টি কলাম জুড়ে ছড়িয়ে পড়েছে। আমি যতটা সম্ভব দক্ষতার সাথে zeros এ এনএ মান কোড কোড করতে চাই।

আমি দুটি বিকল্প দেখি:
1: একটি data.frame রূপান্তর, এবং এই মত কিছু ব্যবহার
2: কিছু ধরনের শীতল data.table সাব সেটিং কমান্ড

আমি টাইপ 1 এর মোটামুটি কার্যকর সমাধান নিয়ে খুশি হব। একটি ডেটা.ফ্রেমে রূপান্তরিত হচ্ছে এবং তারপরে একটি ডেটা.table তে ফিরে খুব বেশি সময় লাগবে না।


আমার বোঝা হল R তে দ্রুত ক্রিয়াকলাপের গোপন ভেক্টর ব্যবহার করা (অথবা অ্যারে, যা হুডের অধীনে ভেক্টর।)

এই সমাধানটিতে আমি একটি data.matrix ব্যবহার করি। data.matrix যা একটি array তবে data.matrix মতো কিছুটা আচরণ করে। এটি একটি অ্যারের কারণ, আপনি NA এর প্রতিস্থাপনের জন্য একটি খুব সহজ ভেক্টর প্রতিস্থাপন ব্যবহার করতে পারেন:

একটি ছোট সাহায্যকারী ফাংশন NA গুলি মুছে ফেলার জন্য। সারাংশ কোড একক লাইন। আমি শুধুমাত্র execution সময় পরিমাপ করতে এই কাজ।

remove_na <- function(x){
  dm <- data.matrix(x)
  dm[is.na(dm)] <- 0
  data.table(dm)
}

একটি প্রদত্ত আকারের data.table . data.table তৈরি করার জন্য একটি ছোট সহায়ক ফাংশন।

create_dt <- function(nrow=5, ncol=5, propNA = 0.5){
  v <- runif(nrow * ncol)
  v[sample(seq_len(nrow*ncol), propNA * nrow*ncol)] <- NA
  data.table(matrix(v, ncol=ncol))
}

একটি ছোট নমুনা উপর বিক্ষোভ:

library(data.table)
set.seed(1)
dt <- create_dt(5, 5, 0.5)

dt
            V1        V2        V3        V4        V5
[1,]        NA 0.8983897        NA 0.4976992 0.9347052
[2,] 0.3721239 0.9446753        NA 0.7176185 0.2121425
[3,] 0.5728534        NA 0.6870228 0.9919061        NA
[4,]        NA        NA        NA        NA 0.1255551
[5,] 0.2016819        NA 0.7698414        NA        NA

remove_na(dt)
            V1        V2        V3        V4        V5
[1,] 0.0000000 0.8983897 0.0000000 0.4976992 0.9347052
[2,] 0.3721239 0.9446753 0.0000000 0.7176185 0.2121425
[3,] 0.5728534 0.0000000 0.6870228 0.9919061 0.0000000
[4,] 0.0000000 0.0000000 0.0000000 0.0000000 0.1255551
[5,] 0.2016819 0.0000000 0.7698414 0.0000000 0.0000000

আমি এখানে আসতে পারব এমন সবচেয়ে সহজ উপায়:

dt[is.na(dt)] <- 0

এটি কার্যকরী এবং ফাংশন এবং অন্যান্য আঠালো কোড লিখতে কোন প্রয়োজন।


এখানে gdata প্যাকেজে gdata ব্যবহার করে একটি সমাধান। আমি বিশাল তথ্য টেবিল তৈরি করার জন্য আন্দ্রে এর সমাধান ব্যবহার করেছি এবং আন্দ্রে এর সমাধান সহ সময় তুলনা অন্তর্ভুক্ত করেছি।

# CREATE DATA TABLE
dt1 = create_dt(2e5, 200, 0.1)

# FUNCTIONS TO SET NA TO ZERO   
f_gdata  = function(dt, un = 0) gdata::NAToUnknown(dt, un)
f_Andrie = function(dt) remove_na(dt)

# COMPARE SOLUTIONS AND TIMES
system.time(a_gdata  <- f_gdata(dt1))

user  system elapsed 
4.224   2.962   7.388 

system.time(a_andrie <- f_Andrie(dt1))

 user  system elapsed 
4.635   4.730  20.060 

identical(a_gdata, g_andrie)  

TRUE

ডেডিকেটেড ফাংশন ( nafill / setnafill ) যে উদ্দেশ্যে সাম্প্রতিক data.table প্যাকেজ

install.packages("data.table", repos="https://Rdatatable.gitlab.io/data.table")

এটি সমান্তরাল ঠিকঠাক ঠিকঠাক ঠিকঠাক কলামগুলিতে প্রক্রিয়া করে যা পূর্বে পোস্ট বেঞ্চমার্কগুলি, তার সময়গুলি এখন পর্যন্ত দ্রুততম পদ্ধতির সাথে, এবং 40 কোরের মেশিন ব্যবহার করেও বাড়িয়েছে।

library(data.table)
create_dt <- function(nrow=5, ncol=5, propNA = 0.5){
  v <- runif(nrow * ncol)
  v[sample(seq_len(nrow*ncol), propNA * nrow*ncol)] <- NA
  data.table(matrix(v, ncol=ncol))
}
f_dowle3 = function(DT) {
  for (j in seq_len(ncol(DT)))
    set(DT,which(is.na(DT[[j]])),j,0)
}

set.seed(1)
dt1 = create_dt(2e5, 200, 0.1)
dim(dt1)
#[1] 200000    200
dt2 = copy(dt1)
system.time(f_dowle3(dt1))
#   user  system elapsed 
#  0.193   0.062   0.254 
system.time(setnafill(dt2, fill=0))
#   user  system elapsed 
#  0.633   0.000   0.020   ## setDTthreads(1) elapsed: 0.149
all.equal(dt1, dt2)
#[1] TRUE

set.seed(1)
dt1 = create_dt(2e7, 200, 0.1)
dim(dt1)
#[1] 20000000    200
dt2 = copy(dt1)
system.time(f_dowle3(dt1))
#   user  system elapsed 
# 22.997  18.179  41.496
system.time(setnafill(dt2, fill=0))
#   user  system elapsed 
# 39.604  36.805   3.798 
all.equal(dt1, dt2)
#[1] TRUE

library(data.table)

DT = data.table(a=c(1,"A",NA),b=c(4,NA,"B"))

DT
    a  b
1:  1  4
2:  A NA
3: NA  B

DT[,lapply(.SD,function(x){ifelse(is.na(x),0,x)})]
   a b
1: 1 4
2: A 0
3: 0 B

শুধু রেফারেন্সের জন্য, gdata বা data.matrix এর তুলনায় ধীর। তবে কেবলমাত্র data.table প্যাকেজ ব্যবহার করে এবং অ সংখ্যাসূচক এন্ট্রিগুলির সাথে মোকাবিলা করতে পারে।


> DT = data.table(a=LETTERS[c(1,1:3,4:7)],b=sample(c(15,51,NA,12,21),8,T),key="a")
> DT
   a  b
1: A 12
2: A NA
3: B 15
4: C NA
5: D 51
6: E NA
7: F 15
8: G 51
> DT[is.na(b),b:=0]
> DT
   a  b
1: A 12
2: A  0
3: B 15
4: C  0
5: D 51
6: E  0
7: F 15
8: G 51
> 




data.table