R Language
आर कोड वैश्वीकरण सर्वोत्तम प्रथाओं
खोज…
पंक्ति संचालन द्वारा
R कोड को वेक्टर करने में कुंजी है, "R फ़ंक्शन द्वारा" या पंक्ति प्रेषण की विधि को कम या समाप्त करना।
इसका मतलब यह है कि जब पहली पंक्ति में "पंक्ति संचालन के द्वारा" किसी समस्या की ओर ध्यान देने की आवश्यकता होती है, जैसे कि प्रत्येक पंक्ति के साधनों की गणना करना, तो किसी को स्वयं से पूछने की आवश्यकता होती है:
- मैं जिन डेटा सेटों के साथ काम कर रहा हूं, वे किस वर्ग के हैं?
- क्या कोई मौजूदा संकलित कोड है जो आर फ़ंक्शन के दोहराए गए मूल्यांकन की आवश्यकता के बिना इसे प्राप्त कर सकता है?
- यदि नहीं, तो क्या मैं पंक्ति के बजाय कॉलम द्वारा ये ऑपरेशन कर सकता हूं?
- अंत में, यह केवल एक साधारण
apply
लूप चलाने के बजाय जटिल सदिश कोड विकसित करने पर बहुत समय बिताने के लायक है? दूसरे शब्दों में, क्या डेटा बड़ा / परिष्कृत है कि R इसे सरल लूप का उपयोग करके कुशलता से संभाल नहीं सकता है?
मेमोरी प्री-एलोकेशन इश्यू और लूप्स में बढ़ते ऑब्जेक्ट को एक तरफ रखते हुए, हम इस उदाहरण पर ध्यान केंद्रित करेंगे कि कैसे लूप्स को apply
करने से बचें, लूप्स के भीतर आर फंक्शंस या री-असेसमेंट आर फंक्शंस का मूल्यांकन करें।
पंक्ति द्वारा माध्य की गणना का एक मानक / आसान तरीका होगा:
apply(mtcars, 1, mean)
Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive Hornet Sportabout Valiant Duster 360
29.90727 29.98136 23.59818 38.73955 53.66455 35.04909 59.72000
Merc 240D Merc 230 Merc 280 Merc 280C Merc 450SE Merc 450SL Merc 450SLC
24.63455 27.23364 31.86000 31.78727 46.43091 46.50000 46.35000
Cadillac Fleetwood Lincoln Continental Chrysler Imperial Fiat 128 Honda Civic Toyota Corolla Toyota Corona
66.23273 66.05855 65.97227 19.44091 17.74227 18.81409 24.88864
Dodge Challenger AMC Javelin Camaro Z28 Pontiac Firebird Fiat X1-9 Porsche 914-2 Lotus Europa
47.24091 46.00773 58.75273 57.37955 18.92864 24.77909 24.88027
Ford Pantera L Ferrari Dino Maserati Bora Volvo 142E
60.97182 34.50818 63.15545 26.26273
लेकिन क्या हम बेहतर कर सकते हैं? आइए देखें कि यहां क्या हुआ:
- सबसे पहले, हमने एक
matrix
लिए एकdata.frame
परिवर्तित किया। (ध्यान दें कि उसका उपयोगapply
फ़ंक्शन के भीतर होता है।) यह अक्षम और खतरनाक दोनों है।matrix
एक समय में कई स्तंभ प्रकारों को नहीं पकड़ सकता है। इसलिए, इस तरह के रूपांतरण से संभवतः जानकारी का नुकसान होगा और कुछ समय के लिए भ्रामक परिणाम (तुलनाapply(iris, 2, class)
sapply(iris, class)
str(iris)
याsapply(iris, class)
)। - सभी में से, हमने प्रत्येक पंक्ति के लिए एक समय, दोहराव से एक ऑपरेशन किया। मतलब, हमें कुछ R फंक्शन
nrow(mtcars)
समय का मूल्यांकन करना था। इस विशिष्ट मामले में,mean
एक कम्प्यूटेशनल रूप से महंगा फ़ंक्शन नहीं है, इसलिए आर आसानी से एक बड़े डेटा सेट के लिए भी इसे आसानी से संभाल सकता है, लेकिन क्या होगा यदि हमें पंक्ति द्वारा मानक विचलन की गणना करने की आवश्यकता है (जिसमें एक महंगा वर्ग रूट ऑपरेशन शामिल है) ? जो हमें अगले बिंदु पर लाता है: - हमने कई बार आर फ़ंक्शन का मूल्यांकन किया, लेकिन शायद पहले से ही इस ऑपरेशन का एक संकलित संस्करण है?
वास्तव में हम बस कर सकता है:
rowMeans(mtcars)
Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive Hornet Sportabout Valiant Duster 360
29.90727 29.98136 23.59818 38.73955 53.66455 35.04909 59.72000
Merc 240D Merc 230 Merc 280 Merc 280C Merc 450SE Merc 450SL Merc 450SLC
24.63455 27.23364 31.86000 31.78727 46.43091 46.50000 46.35000
Cadillac Fleetwood Lincoln Continental Chrysler Imperial Fiat 128 Honda Civic Toyota Corolla Toyota Corona
66.23273 66.05855 65.97227 19.44091 17.74227 18.81409 24.88864
Dodge Challenger AMC Javelin Camaro Z28 Pontiac Firebird Fiat X1-9 Porsche 914-2 Lotus Europa
47.24091 46.00773 58.75273 57.37955 18.92864 24.77909 24.88027
Ford Pantera L Ferrari Dino Maserati Bora Volvo 142E
60.97182 34.50818 63.15545 26.26273
इसमें पंक्ति संचालन द्वारा कोई भी शामिल नहीं है और इसलिए आर कार्यों का दोहराव मूल्यांकन नहीं है। हालाँकि , हमने अभी भी एक matrix
लिए data.frame
परिवर्तित किया है। हालाँकि, rowMeans
में एक एरर हैंडलिंग मैकेनिज़्म है और यह एक डेटा सेट पर नहीं चलेगा, जो इसे हैंडल नहीं कर सकता है, फिर भी इसकी दक्षता लागत है।
rowMeans(iris)
Error in rowMeans(iris) : 'x' must be numeric
लेकिन फिर भी, क्या हम बेहतर कर सकते हैं? हम त्रुटि से निपटने के लिए मैट्रिक्स रूपांतरण के बजाय कोशिश कर सकते हैं, एक अलग विधि जो हमें वेक्टर के रूप में mtcars
का उपयोग करने की अनुमति mtcars
(क्योंकि data.frame
अनिवार्य रूप से एक list
और एक list
एक vector
)।
Reduce(`+`, mtcars)/ncol(mtcars)
[1] 29.90727 29.98136 23.59818 38.73955 53.66455 35.04909 59.72000 24.63455 27.23364 31.86000 31.78727 46.43091 46.50000 46.35000 66.23273 66.05855
[17] 65.97227 19.44091 17.74227 18.81409 24.88864 47.24091 46.00773 58.75273 57.37955 18.92864 24.77909 24.88027 60.97182 34.50818 63.15545 26.26273
अब संभव गति हासिल करने के लिए, हमने कॉलम नाम और त्रुटि हैंडलिंग ( NA
हैंडलिंग सहित) खो दिया है।
एक और उदाहरण समूह द्वारा माध्य की गणना करना होगा, बेस आर का उपयोग करके हम कोशिश कर सकते हैं
aggregate(. ~ cyl, mtcars, mean)
cyl mpg disp hp drat wt qsec vs am gear carb
1 4 26.66364 105.1364 82.63636 4.070909 2.285727 19.13727 0.9090909 0.7272727 4.090909 1.545455
2 6 19.74286 183.3143 122.28571 3.585714 3.117143 17.97714 0.5714286 0.4285714 3.857143 3.428571
3 8 15.10000 353.1000 209.21429 3.229286 3.999214 16.77214 0.0000000 0.1428571 3.285714 3.500000
फिर भी, हम मूल रूप से एक लूप में R फ़ंक्शन का मूल्यांकन कर रहे हैं, लेकिन लूप अब आंतरिक C फ़ंक्शन में छिपा हुआ है (यह बहुत कम मायने रखता है कि यह C या R लूप है)।
क्या हम इससे बच सकते थे? वैसे आर में एक संकलित फ़ंक्शन है जिसे rowsum
कहा जाता है, इसलिए हम ऐसा कर सकते हैं:
rowsum(mtcars[-2], mtcars$cyl)/table(mtcars$cyl)
mpg disp hp drat wt qsec vs am gear carb
4 26.66364 105.1364 82.63636 4.070909 2.285727 19.13727 0.9090909 0.7272727 4.090909 1.545455
6 19.74286 183.3143 122.28571 3.585714 3.117143 17.97714 0.5714286 0.4285714 3.857143 3.428571
8 15.10000 353.1000 209.21429 3.229286 3.999214 16.77214 0.0000000 0.1428571 3.285714 3.500000
हालांकि हमें पहले भी एक मैट्रिक्स में बदलना था।
इस बिंदु पर हम सवाल कर सकते हैं कि क्या हमारी वर्तमान डेटा संरचना सबसे उपयुक्त है। क्या एक data.frame
सबसे अच्छा अभ्यास है? या दक्षता हासिल करने के लिए किसी को matrix
डेटा संरचना पर स्विच करना चाहिए?
जब तक हम हर बार महंगे कार्यों का मूल्यांकन करना शुरू नहीं करेंगे, तब तक पंक्ति संचालन अधिक से अधिक महंगा हो जाएगा (यहां तक कि मैट्रिसेस में भी)। हमें पंक्ति उदाहरण द्वारा एक विचरण गणना पर विचार करने दें।
चलो कहते हैं कि हमारे पास एक मैट्रिक्स m
:
set.seed(100)
m <- matrix(sample(1e2), 10)
m
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 8 33 39 86 71 100 81 68 89 84
[2,] 12 16 57 80 32 82 69 11 41 92
[3,] 62 91 53 13 42 31 60 70 98 79
[4,] 66 94 29 67 45 59 20 96 64 1
[5,] 36 63 76 6 10 48 85 75 99 2
[6,] 18 4 27 19 44 56 37 95 26 40
[7,] 3 24 21 25 52 51 83 28 49 17
[8,] 46 5 22 43 47 74 35 97 77 65
[9,] 55 54 78 34 50 90 30 61 14 58
[10,] 88 73 38 15 9 72 7 93 23 87
एक बस कर सकता है:
apply(m, 1, var)
[1] 871.6556 957.5111 699.2111 941.4333 1237.3333 641.8222 539.7889 759.4333 500.4889 1255.6111
दूसरी ओर, कोई भी पूरी तरह से विचरण के फार्मूले का पालन करके इस ऑपरेशन को पूरी तरह से तैयार कर सकता है
RowVar <- function(x) {
rowSums((x - rowMeans(x))^2)/(dim(x)[2] - 1)
}
RowVar(m)
[1] 871.6556 957.5111 699.2111 941.4333 1237.3333 641.8222 539.7889 759.4333 500.4889 1255.6111