2011-06-06 11 views
5

आर पाठ्यपुस्तक लूप के बजाय लापरवाही के उपयोग को बढ़ावा देना जारी रखती है। यहबदलते तर्कों के साथ लापरवाही का उपयोग

lapply(somelist, f, a=1, b=2) 

पर तर्कों के साथ भी आसान है, लेकिन क्या सूची तत्व के आधार पर तर्क बदलते हैं? मान लें मेरी somelist के होते हैं:

somelist$USA 
somelist$Europe 
somelist$Switzerland 

प्लस वहाँ एक ही क्षेत्रों के साथ anotherlist है और मैं इन बदलते तर्क के साथ lapply का उपयोग करना चाहते हैं? यह उपयोगी हो सकता है जब एफ उदाहरण के लिए अनुपात गणना थी।

lapply(somelist, f, a= somelist$USA, b=anotherlist$USA) 

क्या इन क्षेत्रों के माध्यम से प्रभावी ढंग से चलाने के लिए एक लूप को छोड़कर रास्ता है?

संपादित करें: मेरी समस्या है कि मैं अनुक्रमित बिना किसी पूर्व लिखित फ़ंक्शन का उपयोग करने की कोशिश की है ...

ratio <-function(a,b){ 
z<-(b-a)/a 
return(z) 
} 

जो

lapply(data,ratio,names(data)) 

जो काम नहीं करता है का नेतृत्व किया। शायद अन्य इस गलती से भी सीख सकते हैं।

उत्तर

14

सूची तत्वों की बजाय सूची नामों पर लागू करें। उदा .:

somelist <- list('USA'=rnorm(10), 'Europe'=rnorm(10), 'Switzerland'=rnorm(10)) 
anotherlist <- list('USA'=5, 'Europe'=10, 'Switzerland'=4) 
lapply(names(somelist), function(i) somelist[[i]]/anotherlist[[i]]) 

संपादित करें:

तुम भी अगर वहाँ एक तरीका यह "कुशलता" करने के लिए "एक पाश के लिए छोड़कर" है पूछो। आपको ध्यान रखना चाहिए कि आवेदन आवश्यक रूप से अधिक कुशल नहीं होगा। क्षमता शायद यह निर्धारित की जाएगी कि आपका आंतरिक कार्य कितना तेज़ है। यदि आप किसी सूची के प्रत्येक तत्व पर काम करना चाहते हैं, तो आपको एक लूप की आवश्यकता होगी, चाहे वह किसी लागू() कॉल में छिपा हुआ हो या नहीं। इस सवाल की जाँच करें: Is R's apply family more than syntactic sugar?

उदाहरण मैं ऊपर दे दी है पाश के लिए एक के रूप में फिर से लिखा जा सकता है, और आप कुछ अनुभवहीन मानक बना सकते हैं:

fun1 <- function(){ 
    lapply(names(somelist), function(i) somelist[[i]]/anotherlist[[i]]) 
} 
fun2 <- function(){ 
    for (i in names(somelist)){ 
     somelist[[i]] <- somelist[[i]]/anotherlist[[i]] 
    } 
    return(somelist) 
} 
library(rbenchmark) 

benchmark(fun1(), fun2(), 
      columns=c("test", "replications", 
      "elapsed", "relative"), 
      order="relative", replications=10000) 

मेरी मशीन पर बेंचमार्क के उत्पादन में इस था:

test replications elapsed relative 
1 fun1()  10000 0.145 1.000000 
2 fun2()  10000 0.148 1.020690 

हालांकि यह एक वास्तविक काम आवेदन नहीं है और कार्यों यथार्थवादी कार्य नहीं कर रहे हैं, तो आप देख सकते हैं कि गणना समय में अंतर काफी नगण्य है।

+0

+1 मैं तुम्हें मेरे नाम विचार करने के लिए करने के लिए हरा देखना –

+0

हाँ, यह तरह लग रहा था समस्या को ठीक करने का सबसे सरल तरीका। मैंने बनाम आवेदन के लिए कुछ चर्चा की क्योंकि उसने उस के लिए भी पूछा ... – Vincent

7

आपको केवल lapply() पर काम करने की आवश्यकता है। यहाँ सूचियों का names() पर्याप्त होता है, हम f() पुनर्लेखन के बाद अलग अलग तर्क ले रहे हैं:

somelist <- list(USA = 1:10, Europe = 21:30, 
       Switzerland = seq(1, 5, length = 10)) 
anotherlist <- list(USA = list(a = 1, b = 2), Europe = list(a = 2, b = 4), 
        Switzerland = list(a = 0.5, b = 1)) 

f <- function(x, some, other) { 
    (some[[x]] + other[[x]][["a"]]) * other[[x]][["b"]] 
} 

lapply(names(somelist), f, some = somelist, other = anotherlist) 

देते:

R> lapply(names(somelist), f, some = somelist, other = anotherlist) 
[[1]] 
[1] 4 6 8 10 12 14 16 18 20 22 

[[2]] 
[1] 92 96 100 104 108 112 116 120 124 128 

[[3]] 
[1] 1.500000 1.944444 2.388889 2.833333 3.277778 3.722222 4.166667 4.611111 
[9] 5.055556 5.500000 
+0

बहुत बुरा, मैं यहां एक और +1 नहीं दे सकता। एक और समस्या थी, एसओ पर पूछने की कोशिश की लेकिन सुझाव नहीं दिया कि इसने मुझे इसकी ओर इशारा किया। आपके उत्तरों ने फिर से मदद की! महान। –

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