Neden R'nin ifelse ifadeleri vektörleri döndüremiyor?


118

R'nin ifelse ifadelerinin zaman zaman oldukça kullanışlı olduğunu gördüm. Örneğin:

ifelse(TRUE,1,2)
# [1] 1
ifelse(FALSE,1,2)
# [1] 2

Ama aşağıdaki davranış biraz kafam karıştı.

ifelse(TRUE,c(1,2),c(3,4))
# [1] 1
ifelse(FALSE,c(1,2),c(3,4))
# [1] 3

Bu, maaş notumun üzerinde olan bir tasarım seçimi mi?


1
Ifelse için biraz garip tasarım, eğer başka işe yararsa basit olduğu gerçeği göz önüne alındığında.
2sb

4
ifelse, vektörleştirilmiş bir işlevdir. Farklı görevler için kullanılmaları gerekir.
marbel

Yanıtlar:


99

ifelseEyaletler için belgeler :

ifelseaynı şekle sahip olan bir değer verir test, ya seçilen elemanlardan ile doldurulmuş olan yesya da noelement bağlı olarak testbir TRUEya da FALSE.

1 uzunluğundaki test değerlerini geçtiğiniz için, 1 uzunluğundaki sonuçları alıyorsunuz. Daha uzun test vektörlerini geçerseniz, daha uzun sonuçlar alırsınız:

> ifelse(c(TRUE, FALSE), c(1, 2), c(3, 4))
[1] 1 4

Bu nedenle ifelse, bir boole vektörünü test etmek ve (vektör) yesve noargümanlardan alınan öğelerle dolu aynı uzunlukta bir vektörü döndürmek için özel bir amaç için tasarlanmıştır .

Bunun if () {} else {}yerine gerçekten normal bir yapı istediğinizde bunu kullanmak, işlevin adı nedeniyle yaygın bir karışıklıktır .


16
Belki de ikinci açıklama dizisi için gerçekten istediğiniz şeydi if (TRUE) c(1,2) else c(3,4).
Jonathan Chang

69

Bahse girerim ifbunun yerine basit bir ifade istiyorsunuz ifelse- R'de ifsadece bir kontrol akışı yapısı değildir, bir değer döndürebilir:

> if(TRUE) c(1,2) else c(3,4)
[1] 1 2
> if(FALSE) c(1,2) else c(3,4)
[1] 3 4

@Ken, bu benim için çalışıyor, sürekli bir uyarıya ihtiyacım olanı alsam bile " Warning in if (req(inputval) == "All") { : the condition has length > 1 and only the first element will be used"bu uyarıdan kurtulmak için ne yapmalıyım?
user5249203

1
@ user5249203, soru ve Ken'in cevabı, koşulun tek bir değer, yani uzunluk 1 olan bir vektör olduğu durumu ifade eder. Uyarı req(inputval), daha fazla öğeye sahip olduğunu gösterir . Tek bir değer elde etmek için işlevler any()veya all()yararlı olabilir.
Uwe

12

Sonucu şunun içine atarsanız sorunu aşabileceğinizi unutmayın ifelse:

ifelse(TRUE, a <- c(1,2), a <- c(3,4))
a
# [1] 1 2

ifelse(FALSE, a <- c(1,2), a <- c(3,4))
a
# [1] 3 4

3
IMHO, bu, atama için ifelse()bir kontrol akışı yerine vektörleştirilmiş işlevi kötüye kullanmak için cesaret vericidir if ... else .... Koşul tek TRUEveya FALSEdeğer ise, yazmayı tercih ederim a <- if (TRUE) c(1,2) else c(3,4)veyaif (TRUE) a <- c(1,2) else a <- c(3,4)
Uwe

1
@Uwe ifelseyerine kullanırken performans farkını düşünmesem de if... elsetek bir koşul durumunda gerçekten sorun ifelseolabilir ve bazı durumlarda kod içinde tercih edilebilir (basit tahmin burada), sana katılmıyorum ;-). Sadece bir yol göstermek istedim ifelse.
Cath

9

evet, sanırım ifelse () gerçekten uzun bir test vektörüne sahip olduğunuz ve her birini iki seçenekten birine eşlemek istediğiniz zamanlar için tasarlandı. Örneğin, plot () için genellikle şu şekilde renkler yaparım:

plot(x,y, col = ifelse(x>2,  'red', 'blue'))

Uzun bir test vektörünüz varsa ancak çıktılar için çiftler istiyorsanız, sapply()veya plyr's llply()veya başka bir şey kullanabilirsiniz .


4

Bazen kullanıcının switchbir ifelse. Bu durumda:

condition <- TRUE
switch(2-condition, c(1, 2), c(3, 4))
#### [1] 1 2

(Ken Williams'ın cevabının başka bir sözdizimi seçeneğidir)


4

İşte Cath tarafından önerilene benzer bir yaklaşım, ancak mevcut önceden atanmış vektörlerle çalışabilir

Bu, get()benzerlerini kullanmaya dayanır :

a <- c(1,2)
b <- c(3,4)
get(ifelse(TRUE, "a", "b"))
# [1] 1 2

4

"if" kullanın, örneğin

> `if`(T,1:3,2:4)
[1] 1 2 3

Burada ifelse'nin beklenen işlevselliğini sağlayabilecek tek cevap budur.
sus_mlm

2

Sizin durumunuzda, if_elsefrom kullanmak dplyryardımcı olabilirdi: if_elsedaha katıdır ifelseve vakanız için bir hata verir:

library(dplyr)
if_else(TRUE,c(1,2),c(3,4))
#> `true` must be length 1 (length of `condition`), not 2

0

Everydropr'da bulundu :

ifelse(rep(TRUE, length(c(1,2))), c(1,2),c(3,4))
#>[1] 1 2

İstenilen uzunluğu döndürmek için durumunuzun sonucunu kopyalayabilir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.