यहाँ एक समाधान का उपयोग है 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
। कोई भी डेटा.फ्रेम ऑपरेशन बस काम करेगा।