2014-04-30 9 views
7

मैं आरएमओएनओडीबी के साथ काम कर रहा हूं और मुझे एक क्वेरी के मूल्यों के साथ एक खाली डेटा.फ्रेम भरना होगा। परिणाम काफी लंबे हैं, लगभग 2 मिलियन दस्तावेज़ (पंक्तियां)।धीमी डेटा। फ्रेम पंक्ति असाइनमेंट

जबकि मैं प्रदर्शन परीक्षण कर रहा था, मुझे पता चला कि डेटा फ्रेम के आयाम से पंक्तियों को लिखने का समय बढ़ता है। शायद यह एक प्रसिद्ध मुद्दा है और मैं इसे नोटिस करने वाला अंतिम व्यक्ति हूं।

कुछ कोड उदाहरण:

set.seed(20140430) 
nreg <- 2e3 
dfres <- as.data.frame(matrix(rep(NA,nreg*7),nrow=nreg,ncol=7)) 
system.time(dfres[1e3,] <- c(1:5,"a","b")) 
summary(replicate(10,system.time(dfres[sample(1:nreg,1),] <- c(1:5,"a","b"))[3])) 

nreg <- 2e6 
dfres <- as.data.frame(matrix(rep(NA,nreg*7),nrow=nreg,ncol=7)) 
system.time(dfres[1e3,] <- c(1:5,"a","b")) 
summary(replicate(10,system.time(dfres[sample(1:nreg,1),] <- c(1:5,"a","b"))[3])) 

मेरी मशीन पर, 2 milion पंक्तियों data.frame 0.4 के बारे में सेकंड लेता है पर काम। अगर मैं पूरा डेटासेट भरना चाहता हूं तो यह बहुत समय है। इस मुद्दे को आकर्षित करने के लिए यहां एक दूसरा सिमुलेशन चला जाता है।

nreg <- seq(2e1,2e7,length.out=10) 
te <- NULL 
for(i in nreg){ 
    dfres <- as.data.frame(matrix(rep(NA,i*7),nrow=i,ncol=7)) 
    te <- c(te,mean(replicate(10,{r <- sample(1:i,1); system.time(dfres[r,] <- c(1:5,"a","b"))[3]}))) 
} 
plot(nreg,te,xlab="Number of rows",ylab="Avg. time for 10 random assignments [sec]",type="o") 
#rm(nreg,dfres,te) 

enter image description here

प्रश्न: ऐसा क्यों होता है? क्या स्मृति में डेटा.फ्रेम भरने का कोई तेज तरीका है?

+0

एक workarround: यह 1E4 पंक्तियों के साथ एक अस्थायी data.frame में पंक्तियों बताए जब तक यह भरा हुआ है में होते हैं। फिर मैं इसे अंतिम डेटा के साथ जोड़ता हूं। फ्रेम और छोटे को फिर से भरें। – Emer

उत्तर

11

आइए पहले "कॉलम" से शुरू करें और देखें कि क्या चल रहा है और फिर पंक्तियों पर वापस आना है।

आर संस्करण < 3.1.0 (अनावश्यक रूप से) जब आप उन पर काम करते हैं तो पूरे data.frame की प्रतिलिपि बनाते हैं। उदाहरण के लिए:

## R v3.0.3 
df <- data.frame(x=1:5, y=6:10) 
dplyr:::changes(df, transform(df, z=11:15)) ## requires dplyr to be available 

# Changed variables: 
#   old   new   
# x   0x7ff9343fb4d0 0x7ff9326dfba8 
# y   0x7ff9343fb488 0x7ff9326dfbf0 
# z   <added>  0x7ff9326dfc38 

# Changed attributes: 
#   old   new   
# names  0x7ff934170c28 0x7ff934308808 
# row.names 0x7ff934551b18 0x7ff934308970 
# class  0x7ff9346c5278 0x7ff935d1d1f8 

आप 'नई' स्तंभ की है कि इसके अलावा देख सकते हैं "पुराने" कॉलम की एक प्रति में बदल गया है (पते अलग हैं)। इसके अलावा गुणों की प्रतिलिपि बनाई गई है। सबसे अधिक काटने वाला यह है कि ये प्रतियां गहरी प्रतियां हैं, उथले प्रतियों के विपरीत।

उथला प्रतियां केवल स्तंभ संकेत दिए गए, नहीं पूरे डेटा, जहां के रूप में गहरी प्रतियां सब कुछ (जो यहाँ अनावश्यक है) की प्रतिलिपि के वेक्टर नकल। कि में

हालांकि, आर v3.1.0 में, वहाँ किया गया है अच्छा स्वागत करते हुए परिवर्तन "पुराने" कॉलम गहरी की नकल की नहीं हैं। आर कोर देव टीम के लिए सभी क्रेडिट।

## R v3.1.0 
df <- data.frame(x=1:5, y=6:10) 
dplyr:::changes(df, transform(df, z=11:15)) ## requires dplyr to be available 

# Changed variables: 
#   old  new   
# z   <added> 0x7f85d328dda8 

# Changed attributes: 
#   old   new   
# names  0x7f85d1459548 0x7f85d297bec8 
# row.names 0x7f85d2c66cd8 0x7f85d2bfa928 
# class  0x7f85d345cab8 0x7f85d2d6afb8 

आप देख सकते हैं कि कॉलम x और y नहीं सब पर (और इसलिए changes समारोह कॉल के उत्पादन में मौजूद नहीं) बदल रहे हैं। यह एक बड़ा (और स्वागत है) सुधार है!

अब तक, हम इस मुद्दे पर जोड़ने स्तंभों में आर < 3.1.0 में देखा और v3.1.0


अब, अपने प्रश्न के लिए आ रहा: हां, तो क्या "पंक्तियाँ" के बारे में? आइए पहले आर के पुराने संस्करण पर विचार करें और फिर आर v3.1.0 पर वापस आएं।

## R v3.0.3 
df <- data.frame(x=1:5, y=6:10) 
df.old <- df 
df$y[1L] <- -6L 
dplyr:::changes(df.old, df) 

# Changed variables: 
#   old   new   
# x   0x7f968b423e50 0x7f968ac6ba40 
# y   0x7f968b423e98 0x7f968ac6bad0 
# 
# Changed attributes: 
#   old   new   
# names  0x7f968ab88a28 0x7f968abca8e0 
# row.names 0x7f968abb6438 0x7f968ab22bb0 
# class  0x7f968ad73e08 0x7f968b580828 

एक बार फिर हम देखते हैं कि बदलते स्तंभ y आर के पुराने संस्करणों में रूप में अच्छी तरह नकल स्तंभ x में बदल गया है

## R v3.1.0 
df <- data.frame(x=1:5, y=6:10) 
df.old <- df 
df$y[1L] <- -6L 
dplyr:::changes(df.old, df) 

# Changed variables: 
#   old   new   
# y   0x7f85d3544090 0x7f85d2c9bbb8 
# 
# Changed attributes: 
#   old   new   
# row.names 0x7f85d35a69a8 0x7f85d35a6690 

हम जो सिर्फ स्तंभ y की प्रति में बदल गया है आर v3.1.0 में अच्छा सुधार देखेंगे। एक बार फिर, आर v3.1.0 में महान सुधार! आर की कॉपी-ऑन-संशोधित बुद्धिमान हो गई है।

लेकिन फिर भी, संदर्भ अर्थ विज्ञान द्वारा data.table के काम का उपयोग कर, हम एक कदम बेहतर कर सकते हैं - कॉपी भी y स्तंभ आर v3.1.0 में मामला है के रूप में नहीं।

विचार यह है कि जब तक आप कुछ इंडेक्स पर कॉलम को निर्दिष्ट ऑब्जेक्ट का प्रकार नहीं बदलते हैं (यहां, कॉलम y पूर्णांक है - इसलिए जब तक आप y पर एक पूर्णांक असाइन करते हैं), हम वास्तव मेंइन-प्लेस (संदर्भ द्वारा) संशोधित करके प्रतिलिपि किए बिना इसे कर सकता है।

क्यों? क्योंकि हमें यहां कुछ भी आवंटित/पुनः आवंटित करने की आवश्यकता नहीं है। उदाहरण के तौर पर, यदि आपने एक डबल/न्यूमेरिक प्रकार असाइन किया था, जिसके लिए पूर्णांक कॉलम y के लिए 4-बाइट स्टोरेज के विपरीत 8 बाइट स्टोरेज की आवश्यकता होती है, तो हमें एक नया कॉलम y बनाना होगा और मानों को वापस कॉपी करना होगा।

है यही कारण है कि, हम संदर्भ द्वारा उप-प्रदान कर सकते हैंdata.table का उपयोग कर। ऐसा करने के लिए हम := या set() का उपयोग कर सकते हैं। मैं यहां set() का उपयोग करके प्रदर्शित करूंगा।

अब, यहां आपके डेटा पर बेस आर और data.table के साथ तुलना की गई है, जो 10 के गुणकों में 2,000 से 20,000,000 पंक्तियों के साथ तुलनात्मक रूप से आर v3.0.3 और v3.1.0 के विरुद्ध है। You can find the code here। आर v3.0.3, अनुसंधान के लिए 3.1.0 vs data.table

मिनट, मंझला और अधिकतम:

R3.0.3 vs data.table

आर v3.1.0 के खिलाफ तुलना के लिए प्लॉट:

आर v3.0.3 के खिलाफ तुलना के लिए प्लॉट v3.1.0 और 10 अनुकरण के साथ 20 मिलियन पंक्तियों पर data.table हैं:

 type min median max 
base_3.0.3 10.05 10.70 18.51 
base_3.1.0 1.67 1.97 5.20 
data.table 0.04 0.04 0.05 

नोट: आप this gist में पूरा समय देख सकते हैं।

यह स्पष्ट रूप से आर v3.1.0 में सुधार पता चलता है, लेकिन यह भी पता चलता है कि स्तंभ जो बदला जा रहा है अभी भी कॉपी किया जा रहा है और है कि अभी भी कुछ समय की खपत है, जो data.table में संदर्भ द्वारा उप काम के माध्यम से दूर है ।

HTH

+2

ग्रेट विस्तृत उत्तर। – BrodieG

संबंधित मुद्दे