Sorunun sorduğu gibi, R'de C'nin üçlü operatörüne benzer bir kontrol dizisi var mı? Öyleyse, nasıl kullanıyorsunuz? Teşekkürler!
if (x>1) y=2 else y=3. Yazma y=kez bunu belirli bir çekiciliği vardır.
Sorunun sorduğu gibi, R'de C'nin üçlü operatörüne benzer bir kontrol dizisi var mı? Öyleyse, nasıl kullanıyorsunuz? Teşekkürler!
if (x>1) y=2 else y=3. Yazma y=kez bunu belirli bir çekiciliği vardır.
Yanıtlar:
Gibi ifbir işlevdir Rve en son değerlendirme, if-else eşdeğerdir döndürür ?:.
> a <- 1
> x <- if(a==1) 1 else 2
> x
[1] 1
> x <- if(a==2) 1 else 2
> x
[1] 2
R'nin gücü vektörleştirmedir. Üçlü operatörün vektörleştirilmesi ifelse:
> 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
Şaka yapıyorum, c-stili tanımlayabilirsiniz ?::
`?` <- function(x, y)
eval(
sapply(
strsplit(
deparse(substitute(y)),
":"
),
function(e) parse(text = e)
)[[2 - as.logical(x)]])
burada, parantezlere dikkat etmeniz gerekmez:
> 1 ? 2*3 : 4
[1] 6
> 0 ? 2*3 : 4
[1] 4
> TRUE ? x*2 : 0
[1] 2
> FALSE ? x*2 : 0
[1] 0
ancak atama için parantez gerekir :(
> y <- 1 ? 2*3 : 4
[1] 6
> y
[1] 1
> y <- (1 ? 2*3 : 4)
> y
[1] 6
Son olarak, c ile çok benzer bir şekilde yapabilirsiniz:
`?` <- 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
}
}
Parantezlerden kurtulabilirsiniz:
> 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
Bunlar günlük kullanım için değil, R dilinin bazı iç kısımlarını öğrenmek için iyi olabilir.
Herkesin söylediği gibi, kullanın ifelse, ancak neredeyse üçlü operatör sözdizimine sahip olmak için işleçleri tanımlayabilirsiniz.
`%?%` <- 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
Aslında operatörleri işaretsiz olarak tanımlarsanız çalışır %, böylece
`?` <- 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"
(Bu işe yarar çünkü önceliği :daha düşüktür ?.)
Ne yazık ki, bu durum mevcut yardım ve dizi operatörlerini bozuyor.
Sadece bir şaka gibi, sen yapabilirsiniz yeniden tanımlamak ?üçlü operatörü gibi (neredeyse) işe operatörü (bu kötü bir fikir IS):
`?` <- 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")
... Ancak ifadeleri parantez içine almanız gerekir, çünkü varsayılan öncelik C'deki gibi değildir.
Oynamayı bitirdiğinizde eski yardım işlevini geri yüklemeyi unutmayın:
rm(`?`)
ifelseKomuta bir göz atarım. Daha da iyi derdim çünkü aynı zamanda vektörize. Araba veri kümesini kullanan bir örnek:
> 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"
ifelsemi göstermek istediniz ? ;)
Bağlantınız bir ififadeye işaret ediyor .
> x <- 1
> if(x < 2) print("Less than") else print("Greater than")
[1] "Less than"
Girdi değişkeniniz bir vektörse, ifelsedaha uygun olabilir:
> x <- 1:3
> ifelse(x<=2, "Less than or equal", "Greater than")
[1] "Less than or equal" "Less than or equal" "Greater than"
İçin yardım sayfasına erişmek için if, ifters tırnakları yerleştirmeniz gerekir :
?`if`
İçin yardım sayfası ifelse:
`?ifelse`
print(if (x<2) "Less than" else "Greater than")
Açıkça mevcut değil, ancak şunları yapabilirsiniz:
set.seed(21)
y <- 1:10
z <- rnorm(10)
condition1 <- TRUE
x1 <- if(condition1) y else z
veya
condition2 <- sample(c(TRUE,FALSE),10,TRUE)
x2 <- ifelse(condition2, y, z)
İkisi arasındaki fark olduğunu condition1iken, uzunluğu 1 mantıksal bir vektör olmalıdır condition2ile aynı uzunlukta bir mantıksal vektörü olmalıdır x, yve z. Birincisi ya yda z(nesnenin tamamı), ikincisi ise y( condition2==TRUE) veya z( condition2==FALSE) öğesinin karşılık gelen öğesini döndürür .
Dikkat edilmesi gereken ifelsedaha yavaş olacaktır if/ ' elseise condition, yve zuzunluğu 1 ile bütün vektörler bulunmaktadır.
if aşağıdaki şekilde kullanılırsa, vektörsüz ifelse gibi çalışır:
`if`(condition, doIfTrue, doIfFalse)
Bunu ifelse üzerinden kullanmanın avantajı, vektörizasyonun yolunda olduğu zamandır (yani sonuç olarak skaler boole ve liste / vektör şeyleri var)
ifelse(TRUE, c(1,2), c(3,4))
[1] 1
`if`(TRUE, c(1,2), c(3,4))
[1] 1 2
ifelseyoksa sadece daha kompakt bir form mu istiyorsunuz?