यहाँ एक समाधान का उपयोग है 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पूरे डेटासेट की एक स्थानीय प्रतिलिपि बनाने के लिए फ़ंक्शन को एक स्पष्ट कॉल की आवश्यकता होती है। data.table's 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वेक्टर में संदर्भ द्वारा अद्यतन होने वाले छोटे na.replace C फ़ंक्शन को लिखकर उन्हें आसानी से समाप्त किया जा सकता है । मुझे लगता है कि कम से कम 20 सेकंड आधा कर दिया। क्या इस तरह के फ़ंक्शन किसी भी आर पैकेज में मौजूद हैं?
कारण f_andrieविफल हो सकता है क्योंकि यह संपूर्ण की प्रतिलिपि dt1बनाता है, या तार्किक मैट्रिक्स को पूरे के बड़े dt1, कुछ समय में बनाता है । अन्य 2 विधियाँ एक समय में एक कॉलम पर काम करती हैं (हालाँकि मैंने केवल संक्षेप में देखा था NAToUnknown)।
EDIT (टिप्पणियों में रामनाथ द्वारा अनुरोध के रूप में अधिक सुरुचिपूर्ण समाधान):
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 (1 साल बाद, अब)
भी है 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। कोई भी डेटा.फ्रेम ऑपरेशन बस काम करेगा।