Seperti yang ditanyakan, apakah ada urutan kontrol dalam R yang mirip dengan operator ternary C ? Jika demikian, bagaimana Anda menggunakannya? Terima kasih!
if (x>1) y=2 else y=3. Menulis y=sekali memiliki daya tarik tertentu untuk itu.
Seperti yang ditanyakan, apakah ada urutan kontrol dalam R yang mirip dengan operator ternary C ? Jika demikian, bagaimana Anda menggunakannya? Terima kasih!
if (x>1) y=2 else y=3. Menulis y=sekali memiliki daya tarik tertentu untuk itu.
Jawaban:
Seperti ifberfungsi Rdan mengembalikan evaluasi terbaru, jika-lain setara dengan ?:.
> a <- 1
> x <- if(a==1) 1 else 2
> x
[1] 1
> x <- if(a==2) 1 else 2
> x
[1] 2
Kekuatan R adalah vektorisasi. Vektorisasi operator ternary adalah 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
Hanya bercanda, Anda dapat mendefinisikan c-style ?::
`?` <- function(x, y)
eval(
sapply(
strsplit(
deparse(substitute(y)),
":"
),
function(e) parse(text = e)
)[[2 - as.logical(x)]])
di sini, Anda tidak perlu peduli tentang tanda kurung:
> 1 ? 2*3 : 4
[1] 6
> 0 ? 2*3 : 4
[1] 4
> TRUE ? x*2 : 0
[1] 2
> FALSE ? x*2 : 0
[1] 0
tetapi Anda membutuhkan tanda kurung untuk penugasan :(
> y <- 1 ? 2*3 : 4
[1] 6
> y
[1] 1
> y <- (1 ? 2*3 : 4)
> y
[1] 6
Akhirnya, Anda dapat melakukan cara yang sangat mirip dengan c:
`?` <- 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
}
}
Anda dapat menyingkirkan tanda kurung:
> 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
Ini bukan untuk penggunaan sehari-hari, tetapi mungkin baik untuk mempelajari beberapa bahasa R internal.
Seperti kata orang lain, gunakan ifelse, tetapi Anda dapat mendefinisikan operator sehingga Anda hampir memiliki sintaksis operator ternary.
`%?%` <- 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
Ini benar-benar berfungsi jika Anda mendefinisikan operator tanpa %tanda, sehingga Anda dapat melakukannya
`?` <- 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"
(Ini berfungsi karena diutamakan :lebih rendah daripada ?.)
Sayangnya, itu kemudian merusak bantuan dan urutan operator yang ada.
Sama seperti sebuah lelucon, Anda dapat mendefinisikan kembali ?operator untuk (hampir) bekerja seperti operator ternary (INI ADALAH BAD IDEA):
`?` <- 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")
... Tapi Anda harus meletakkan ekspresi di dalam tanda kurung karena presedensi default tidak seperti dalam C.
Ingatlah untuk mengembalikan fungsi bantuan lama saat Anda selesai bermain:
rm(`?`)
Saya akan melihat ifelseperintah. Saya akan menyebutnya lebih baik karena itu juga vektor. Contoh menggunakan dataset mobil:
> 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"
ifelsecontoh Anda? ;)
Tautan Anda menunjuk ke sebuah ifpernyataan.
> x <- 1
> if(x < 2) print("Less than") else print("Greater than")
[1] "Less than"
Jika variabel input Anda adalah vektor, maka ifelsemungkin lebih cocok:
> x <- 1:3
> ifelse(x<=2, "Less than or equal", "Greater than")
[1] "Less than or equal" "Less than or equal" "Greater than"
Untuk mengakses halaman bantuan if, Anda harus menyematkan ifbacktick di:
?`if`
Halaman bantuan untuk ifelseberada di:
`?ifelse`
print(if (x<2) "Less than" else "Greater than")
Tidak ada secara eksplisit, tetapi Anda dapat melakukannya:
set.seed(21)
y <- 1:10
z <- rnorm(10)
condition1 <- TRUE
x1 <- if(condition1) y else z
atau
condition2 <- sample(c(TRUE,FALSE),10,TRUE)
x2 <- ifelse(condition2, y, z)
Perbedaan antara keduanya adalah bahwa condition1harus menjadi vektor logis dari panjang 1, sementara condition2harus menjadi vektor logis panjang yang sama dengan x, y, dan z. Yang pertama akan mengembalikan salah satu yatau z(seluruh objek), sedangkan yang kedua akan mengembalikan elemen yang sesuai dari y( condition2==TRUE) atau z( condition2==FALSE).
Juga catatan itu ifelseakan lebih lambat dari if/ elsejika condition, ydan zsemua vektor dengan panjang 1.
if berfungsi seperti ifelse yang tidak di-revisi jika digunakan dengan cara berikut:
`if`(condition, doIfTrue, doIfFalse)
Keuntungan menggunakan ini lebih dari ifelse adalah ketika vektorisasi di jalan (yaitu saya punya skalar boolean dan daftar / hal vektor sebagai hasilnya)
ifelse(TRUE, c(1,2), c(3,4))
[1] 1
`if`(TRUE, c(1,2), c(3,4))
[1] 1 2
ifelse, atau hanya bentuk yang lebih kompak?