2012-01-09 24 views
122

जैसा सवाल पूछता है, क्या सी में ternary operator के समान आर में नियंत्रण अनुक्रम है? यदि हां, तो आप इसका उपयोग कैसे करते हैं? धन्यवाद!क्या टर्नरी ऑपरेटर आर में मौजूद है?

+1

क्या आप 'ifelse' से अधिक शक्तिशाली चाहते हैं, या बस एक और कॉम्पैक्ट फॉर्म? –

+0

@CarlWitthoft अधिकतर कॉम्पैक्ट फॉर्म; लिखने के लिए बस एक तरीका 'अगर (x> 1) y = 2 else y = 3'। लेखन 'y = 'एक बार इसके लिए एक निश्चित अपील है। – eykanal

उत्तर

205

if रूप में, अगर-बाकी ?: के बराबर है।

> a <- 1 
> x <- if(a==1) 1 else 2 
> x 
[1] 1 
> x <- if(a==2) 1 else 2 
> x 
[1] 2 

आर की शक्ति वेक्टरेशन है। त्रिगुट ऑपरेटर के vectorization ifelse है:

`?` <- function(x, y) 
    eval(
      sapply(
        strsplit(
          deparse(substitute(y)),  
          ":" 
     ),  
      function(e) parse(text = e) 
   )[[2 - as.logical(x)]]) 
यहाँ

, आप कोष्ठक के बारे में देखभाल करने के लिए की जरूरत नहीं है:

> a <- c(1, 2, 1) 
> x <- ifelse(a==1, 1, 2) 
> x 
[1] 1 2 1 
> x <- ifelse(a==2, 1, 2) 
> x 
[1] 2 1 2 

बस मजाक कर रहे हैं, तो आप सी शैली ?: परिभाषित कर सकते हैं:

> 1 ? 2*3 : 4 
[1] 6 
> 0 ? 2*3 : 4 
[1] 4 
> TRUE ? x*2 : 0 
[1] 2 
> FALSE ? x*2 : 0 
[1] 0 

लेकिन आप काम के लिए कोष्ठक की जरूरत है :(

+०१२३५१६४१०६
> y <- 1 ? 2*3 : 4 
[1] 6 
> y 
[1] 1 
> y <- (1 ? 2*3 : 4) 
> y 
[1] 6 

अंत में, आप ग के साथ बहुत समान तरीके से कर सकते हैं:

`?` <- function(x, y) { 
    xs <- as.list(substitute(x)) 
    if (xs[[1]] == as.name("<-")) x <- eval(xs[[3]]) 
    r <- eval(sapply(strsplit(deparse(substitute(y)), ":"), function(e) parse(text = e))[[2 - as.logical(x)]]) 
    if (xs[[1]] == as.name("<-")) { 
    xs[[3]] <- r 
     eval.parent(as.call(xs)) 
    } else { 
    r 
    } 
}  

आप कोष्ठक से छुटकारा पाने के कर सकते हैं:

> y <- 1 ? 2*3 : 4 
> y 
[1] 6 
> y <- 0 ? 2*3 : 4 
> y 
[1] 4 
> 1 ? 2*3 : 4 
[1] 6 
> 0 ? 2*3 : 4 
[1] 4 

ये दैनिक उपयोग के लिए नहीं हैं, लेकिन हो सकता है आर भाषा के कुछ आंतरिक सीखने के लिए अच्छा है।

3

मैं ifelse कमांड पर एक नज़र डालेगा। मैं इसे और भी बेहतर कहूंगा क्योंकि यह भी सदिश है। एक उदाहरण कारों डेटासेट का उपयोग करके:

> cars$speed > 20 
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
[37] FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE 
[49] TRUE TRUE 

> ifelse(cars$speed > 20, 'fast', 'slow') 
[1] "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" 
[11] "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" 
[21] "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" 
[31] "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" "slow" 
[41] "slow" "slow" "slow" "fast" "fast" "fast" "fast" "fast" "fast" "fast" 
+4

हाय पॉल - क्या आपका मतलब है कि आपके उदाहरण के साथ 'ifelse' के बारे में कुछ दिखाना है?;) –

+0

कोई इरादा नहीं था, लेकिन यह अनजान हो सकता है;) –

3

आपका लिंक एक if बयान के अंक।

> x <- 1 
> if(x < 2) print("Less than") else print("Greater than") 
[1] "Less than" 

अपने इनपुट चर एक वेक्टर है, तो ifelse अधिक उपयुक्त हो सकता है:

> x <- 1:3 
> ifelse(x<=2, "Less than or equal", "Greater than") 
[1] "Less than or equal" "Less than or equal" "Greater than" 

if के लिए मदद पृष्ठ का उपयोग करने के लिए आपको बैकटिक में if एम्बेड करने के लिए की जरूरत है:

?`if` 

ifelse के लिए सहायता पृष्ठ एक है टी: समारोह R में है और नवीनतम मूल्यांकन रिटर्न

`?ifelse` 
+1

जैसा कि @ कोहस्के ने कहा, यह भी काम करेगा: 'प्रिंट (अगर (x <2) "से कम" अन्य "से बड़ा") –

3

यह स्पष्ट मौजूद नहीं है, लेकिन आप कर सकते हैं:

set.seed(21) 
y <- 1:10 
z <- rnorm(10) 

condition1 <- TRUE 
x1 <- if(condition1) y else z 

या

condition2 <- sample(c(TRUE,FALSE),10,TRUE) 
x2 <- ifelse(condition2, y, z) 

दोनों के बीच अंतर यह है कि condition1, लंबाई 1 के एक तार्किक वेक्टर होना चाहिए, जबकि condition2 है x, y, और z जैसी लॉजिकल वेक्टर होना चाहिए। पहला y या z (संपूर्ण ऑब्जेक्ट) लौटाएगा, जबकि दूसरा y (condition2==TRUE) या z (condition2==FALSE) के संबंधित तत्व को वापस करेगा।

भी ध्यान रखें कि ifelse धीमी गति से if/else अगर condition, y, और z लंबाई के साथ सभी वैक्टर 1.

+0

धन्यवाद यहोशू , आपके उत्तर ने बहुत मदद की, मुझे आपके द्वारा उल्लिखित पोस्ट से उत्तर मिला http://stackoverflow.com/a/8792474/3019570 –

16

की तरह हर किसी ने कहा, का उपयोग ifelse हैं होगा, लेकिन आप ऑपरेटरों परिभाषित कर सकते हैं, ताकि आप लगभग टर्नरी ऑपरेटर सिंटैक्स है।

`%?%` <- function(x, y) list(x = x, y = y) 
`%:%` <- function(xy, z) if(xy$x) xy$y else z 

TRUE %?% rnorm(5) %:% month.abb 
## [1] 0.05363141 -0.42434567 -0.20000319 1.31049766 -0.31761248 
FALSE %?% rnorm(5) %:% month.abb 
## [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec" 
# or, more generally 
condition %?% value1 %:% value2 

यह वास्तव में अगर आप % लक्षण के बिना ऑपरेटरों को परिभाषित है, अतः आपको

`?` <- function(x, y) if(x) y[[1]] else y[[2]] 
`:` <- function(y, z) list(y, z) 

TRUE ? rnorm(5) : month.abb 
## [1] 1.4584104143 0.0007500051 -0.7629123322 0.2433415442 0.0052823403 
FALSE ? rnorm(5) : month.abb 
## [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec" 

(इसका कारण यह है काम करता है : की पूर्वता ? से कम है।)

दुर्भाग्य से हो सकता था , जो तब मौजूदा सहायता और अनुक्रम ऑपरेटर को तोड़ देता है।

3

बस एक मज़ाक के रूप में, आप को फिर से परिभाषित कर सकते हैं करने के लिए (लगभग) त्रिगुट ऑपरेटर की तरह काम ? ऑपरेटर (यह एक बुरा विचार है):

`?` <- function(x, y) { y <-substitute(y); if(x) eval(y[[2]], parent.frame()) else eval(y[[3]], parent.frame()) } 

x <- 1:3 
length(x) ? (x*2) : 0 
x <- numeric(0) 
length(x) ? (x*2) : 0 

for(i in 1:5) cat(i, (i %% 2) ? "Odd\n" : "Even\n") 

... लेकिन आप लगाने की जरूरत है कोष्ठक में भाव क्योंकि डिफ़ॉल्ट पूर्वता सी

में पसंद नहीं है बस पुराने मदद समारोह बहाल करने के लिए याद है जब आप खेल रहे हैं काम हो गया:

rm(`?`) 
0

if unvectorised ifelse की तरह काम करता है, तो निम्नलिखित तरीके से इस्तेमाल किया:

`if`(condition, doIfTrue, doIfFalse) 

ifelse पर इस उपयोग करने का लाभ जब vectorisation रास्ते में है (यानी मैं अदिश बूलियन और सूची/एक परिणाम के रूप वेक्टर बातें हैं) है

ifelse(TRUE, c(1,2), c(3,4)) 
[1] 1 
`if`(TRUE, c(1,2), c(3,4)) 
[1] 1 2 
संबंधित मुद्दे