এখানে একটি সলিউশন ব্যবহার এর data.table এর :=
অপারেটর, Andrie এবং রামনাথ এর উত্তরের উপর বিল্ডিং।
require(data.table) # v1.6.6
require(gdata) # v2.8.2
set.seed(1)
dt1 = create_dt(2e5, 200, 0.1)
dim(dt1)
[1] 200000 200 # more columns than Ramnath's answer which had 5 not 200
f_andrie = function(dt) remove_na(dt)
f_gdata = function(dt, un = 0) gdata::NAToUnknown(dt, un)
f_dowle = function(dt) { # see EDIT later for more elegant solution
na.replace = function(v,value=0) { v[is.na(v)] = value; v }
for (i in names(dt))
eval(parse(text=paste("dt[,",i,":=na.replace(",i,")]")))
}
system.time(a_gdata = f_gdata(dt1))
user system elapsed
18.805 12.301 134.985
system.time(a_andrie = f_andrie(dt1))
Error: cannot allocate vector of size 305.2 Mb
Timing stopped at: 14.541 7.764 68.285
system.time(f_dowle(dt1))
user system elapsed
7.452 4.144 19.590 # EDIT has faster than this
identical(a_gdata, dt1)
[1] TRUE
নোট করুন যে রেফারেন্স দ্বারা f_dowle dt1 আপডেট হয়েছে। যদি কোনও স্থানীয় অনুলিপি প্রয়োজন হয় তবে copy
পুরো ডেটাসেটের স্থানীয় অনুলিপি তৈরি করতে ফাংশনে একটি স্পষ্ট কল প্রয়োজন। ডেটা.টাবলের setkey
, key<-
এবং :=
অনুলিপি অনুলিপি না।
এরপরে, আসুন দেখা যাক f_dowle কোথায় সময় কাটাচ্ছে।
Rprof()
f_dowle(dt1)
Rprof(NULL)
summaryRprof()
$by.self
self.time self.pct total.time total.pct
"na.replace" 5.10 49.71 6.62 64.52
"[.data.table" 2.48 24.17 9.86 96.10
"is.na" 1.52 14.81 1.52 14.81
"gc" 0.22 2.14 0.22 2.14
"unique" 0.14 1.36 0.16 1.56
... snip ...
সেখানে আমি মনোনিবেশ করব na.replace
এবং is.na
যেখানে কয়েকটি ভেক্টর অনুলিপি এবং ভেক্টর স্ক্যান রয়েছে। এগুলি খুব সহজেই একটি ছোট না.রেপ্লেস সি ফাংশন লিখে ভ্যাক্টরের NA
রেফারেন্স অনুসারে আপডেট করা যায়। এটি আমার মনে হয় কমপক্ষে 20 সেকেন্ডে অর্ধেক হয়ে যাবে। কোনও আর প্যাকেজে কি এই জাতীয় ফাংশন বিদ্যমান?
কারণ f_andrie
ব্যর্থ হতে পারে, কারণ এটি কপি পুরো dt1
বা পুরো হিসাবে হিসাবে বড় একটি লজিক্যাল ম্যাট্রিক্স সৃষ্টি dt1
, কয়েক বার। অন্যান্য 2 টি পদ্ধতি একবারে একটি কলামে কাজ করে (যদিও আমি কেবল সংক্ষেপে তাকিয়েছি NAToUnknown
)।
সম্পাদনা (মন্তব্যগুলিতে রামনাথের অনুরোধ হিসাবে আরও মার্জিত সমাধান):
f_dowle2 = function(DT) {
for (i in names(DT))
DT[is.na(get(i)), (i):=0]
}
system.time(f_dowle2(dt1))
user system elapsed
6.468 0.760 7.250 # faster, too
identical(a_gdata, dt1)
[1] TRUE
আমি আশা করি আমি এটি দিয়ে শুরু করেছিলাম!
EDIT2 (এক বছরেরও বেশি পরে, এখন)
এছাড়াও আছে set()
। এটি যদি [,:=,]
লুপের মধ্যে কলিংয়ের (ছোট) ওভারহেডকে এড়িয়ে চলে তবে প্রচুর কলামটি লুপ করা হচ্ছে এমনটি দ্রুত হতে পারে । set
একটি লুপযোগ্য :=
। দেখুন ?set
।
f_dowle3 = function(DT) {
# either of the following for loops
# by name :
for (j in names(DT))
set(DT,which(is.na(DT[[j]])),j,0)
# or by number (slightly faster than by name) :
for (j in seq_len(ncol(DT)))
set(DT,which(is.na(DT[[j]])),j,0)
}
data.table
একটি থেকেdata.frame
? কdata.table
হয় কdata.frame
। যে কোনও ডেটা ফ্রেম অপারেশন কেবল কাজ করবে will