Saya mencoba untuk menguji apakah semua elemen vektor sama satu sama lain. Solusi yang saya temukan tampaknya agak tidak langsung, keduanya melibatkan pemeriksaan length()
.
x <- c(1, 2, 3, 4, 5, 6, 1) # FALSE
y <- rep(2, times = 7) # TRUE
Dengan unique()
:
length(unique(x)) == 1
length(unique(y)) == 1
Dengan rle()
:
length(rle(x)$values) == 1
length(rle(y)$values) == 1
Solusi yang memungkinkan saya menyertakan nilai toleransi untuk menilai 'kesetaraan' di antara elemen akan ideal untuk menghindari masalah FAQ 7.31 .
Apakah ada fungsi bawaan untuk jenis pengujian yang telah saya abaikan sepenuhnya? identical()
dan all.equal()
membandingkan dua objek R, sehingga tidak akan berfungsi di sini.
Edit 1
Berikut beberapa hasil benchmarking. Menggunakan kode:
library(rbenchmark)
John <- function() all( abs(x - mean(x)) < .Machine$double.eps ^ 0.5 )
DWin <- function() {diff(range(x)) < .Machine$double.eps ^ 0.5}
zero_range <- function() {
if (length(x) == 1) return(TRUE)
x <- range(x) / mean(x)
isTRUE(all.equal(x[1], x[2], tolerance = .Machine$double.eps ^ 0.5))
}
x <- runif(500000);
benchmark(John(), DWin(), zero_range(),
columns=c("test", "replications", "elapsed", "relative"),
order="relative", replications = 10000)
Dengan hasil:
test replications elapsed relative
2 DWin() 10000 109.415 1.000000
3 zero_range() 10000 126.912 1.159914
1 John() 10000 208.463 1.905251
Jadi sepertinya diff(range(x)) < .Machine$double.eps ^ 0.5
yang tercepat.
system.time(for(i in 1:1e4) zero_range(x))
, dari manax
dari OP. Solusi John ~ 10x untukx
, ~ 3x lebih cepat untuky
dan sedikit lebih lambat untukrunif(1e6)
.Mengapa tidak hanya menggunakan varians:
Jika semua elemen
x
sama, Anda akan mendapatkan varian sebesar0
.sumber
length(unique(x))=1
akhirnya menjadi sekitar dua kali lebih cepat, tetapivar
singkat dan itu bagus.John test: TRUE ; DWin test: TRUE ; zero-range test: TRUE ; variance test: FALSE
arti semua tes lainnya mengenali bahwa nilai-nilai identik dalam R. Bagaimana uji varians dapat digunakan dalam konteks itu?TRUE
? Dalam kasus jawaban John, Anda memeriksa apakah perbedaannya di atas ambang tertentu. Dalam kasus Anda, perbedaan antara 2 nilai tersebut sangat rendah, yang dapat membuatnya berada di bawah ambang batas yang Anda tetapkan.Jika semuanya nilai numerik maka jika tol adalah toleransi Anda maka ...
adalah solusi untuk masalah Anda.
EDIT:
Setelah melihat ini, dan jawaban lainnya, dan membandingkan beberapa hal berikut ini keluar dua kali lebih cepat dari jawaban DWin.
Ini sedikit mengejutkan lebih cepat daripada
diff(range(x))
karenadiff
seharusnya tidak jauh berbeda dari-
danabs
dengan dua angka. Meminta kisaran harus mengoptimalkan mendapatkan minimum dan maksimum. Keduanyadiff
danrange
merupakan fungsi primitif. Tapi waktunya tidak berbohong.sumber
Lainnya di sepanjang garis yang sama:
sumber
x <- seq(1, 10) / 1e10
Anda dapat menggunakan
identical()
danall.equal()
dengan membandingkan elemen pertama dengan elemen lainnya, secara efektif menyapu perbandingan di:Dengan cara itu Anda dapat menambahkan epsilon apa pun
identical()
sesuai kebutuhan.sumber
Anda tinggal memeriksanya
all(v==v[1])
sumber
NA
di vektor Anda:x <- c(1,1,NA); all(x == x[1])
returnNA
, notFALSE
. Dalam kasus seperti itulength(unique(x)) == 1
berhasil.Karena saya terus kembali ke pertanyaan ini berulang kali, berikut adalah
Rcpp
solusi yang umumnya akan jauh lebih cepat daripadaR
solusi mana pun jika jawabannya benar-benarFALSE
(karena itu akan berhenti saat menemui ketidakcocokan) dan akan memiliki kecepatan yang sama sebagai solusi R tercepat jika jawabannya adalahTRUE
. Misalnya untuk benchmark OP,system.time
clock tepat 0 menggunakan fungsi ini.sumber
fast_equal(c(2,1,3), 1.5)
a == b
,b == c
tidak selalu berartia == c
jika Anda melakukan perbandingan floating point. Anda dapat membagi presisi Anda dengan jumlah elemen untuk menghindari masalah ini, atau memodifikasi algoritme untuk menghitungmin
danmax
dan menggunakannya sebagai kondisi penghentian.Saya menulis fungsi khusus untuk ini, yang tidak hanya dapat memeriksa elemen dalam vektor, tetapi juga mampu memeriksa apakah semua elemen dalam daftar identik . Tentu saja itu juga menangani vektor karakter dan semua jenis vektor lainnya dengan baik. Ini juga memiliki penanganan kesalahan yang tepat.
Sekarang coba beberapa contoh.
sumber
Anda sebenarnya tidak perlu menggunakan min, mean, atau max. Berdasarkan jawaban John:
sumber
Di sini alternatif menggunakan trik min, max tetapi untuk bingkai data. Dalam contoh saya membandingkan kolom tetapi parameter margin dari
apply
dapat diubah menjadi 1 untuk baris.Jika
valid == 0
kemudian semua elemennya samasumber