एकल वेक्टर के सभी तत्वों के बीच समानता के लिए परीक्षण करें


101

मैं यह जांचने की कोशिश कर रहा हूं कि क्या वेक्टर के सभी तत्व एक दूसरे के बराबर हैं। मैं जिन समाधानों के साथ आया हूं, वे कुछ हद तक चौकाने वाले हैं, दोनों में जाँच शामिल है length()

x <- c(1, 2, 3, 4, 5, 6, 1)  # FALSE
y <- rep(2, times = 7)       # TRUE

के साथ unique():

length(unique(x)) == 1
length(unique(y)) == 1

के साथ rle():

length(rle(x)$values) == 1
length(rle(y)$values) == 1

एक समाधान जो मुझे तत्वों के बीच 'समानता' का आकलन करने के लिए एक सहिष्णुता मूल्य शामिल करने देता है, एफएक्यू 7.31 मुद्दों से बचने के लिए आदर्श होगा ।

क्या परीक्षण के प्रकार के लिए एक अंतर्निहित कार्य है जिसे मैंने पूरी तरह से अनदेखा कर दिया है? identical()और all.equal()दो आर वस्तुओं की तुलना करें, इसलिए वे यहां काम नहीं करेंगे।

संपादित करें 1

यहां कुछ बेंचमार्किंग परिणाम दिए गए हैं। कोड का उपयोग करना:

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)

परिणामों के साथ:

          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

तो ऐसा लग रहा है diff(range(x)) < .Machine$double.eps ^ 0.5कि सबसे तेज है।

जवाबों:


37

मैं इस विधि का उपयोग करता हूं, जो कि औसत से विभाजित करने के बाद न्यूनतम और अधिकतम की तुलना करता है:

# Determine if range of vector is FP 0.
zero_range <- function(x, tol = .Machine$double.eps ^ 0.5) {
  if (length(x) == 1) return(TRUE)
  x <- range(x) / mean(x)
  isTRUE(all.equal(x[1], x[2], tolerance = tol))
}

यदि आप इसे और अधिक गंभीरता से उपयोग कर रहे हैं, तो आप शायद रेंज और माध्य की गणना करने से पहले लापता मूल्यों को हटाना चाहेंगे।


मैंने इसे डिर्क की तुलना में तेज़ होने के लिए चुना। मेरे पास लाखों तत्व नहीं हैं, लेकिन यह मेरे लिए थोड़ा तेज चलना चाहिए।
किमी

@ केविन: जॉन के समाधान के बारे में क्या? यह हैडली की तुलना में ~ 10x तेज है और आपको सहिष्णुता स्थापित करने की अनुमति देता है। क्या यह किसी और तरह से कमी है?
जोशुआ उलरिच

कृपया कुछ बेंचमार्किंग प्रदान करें - मैंने अभी चेक किया मेरा एक मिलियन वर्दी के वेक्टर के लिए समान है।
हेली

@ अहदले: मैं भाग रहा था system.time(for(i in 1:1e4) zero_range(x)), जहाँ xओपी था। जॉन का समाधान ~ 10x के लिए x, ~ 3x तेज के लिए yऔर थोड़ा धीमा है runif(1e6)
जोशुआ उलरिच

जब आप 0.00023 और 0.000023 सेकंड के बीच के अंतर को देख रहे हैं तो 10x का अंतर बहुत मायने नहीं रखता है - और डीडिन शायद यह दावा करेंगे कि वे सहिष्णुता के निर्दिष्ट डिग्री के समान हैं;)
हैडली

46

बस विचरण का उपयोग क्यों नहीं कर रहे हैं:

var(x) == 0

यदि सभी तत्व xसमान हैं, तो आप का विचरण करेंगे 0


17
length(unique(x))=1के बारे में दो बार उपवास के रूप में समाप्त होता है, लेकिन varयह अच्छा है।
एडमो

YohanBadia, मेरे पास एक सरणी c (-5.532456e-09, 1.695298e-09) है, और इसका John test: TRUE ; DWin test: TRUE ; zero-range test: TRUE ; variance test: FALSEअर्थ है कि अन्य सभी परीक्षण पहचानते हैं कि मान R में समान हैं। उस संदर्भ में विचरण परीक्षण का उपयोग कैसे किया जा सकता है?
एमजे

आपके सरणी में 2 मान समान नहीं हैं। आप परीक्षण क्यों लौटना TRUEचाहेंगे? जॉन के जवाब के मामले में, आप जांचते हैं कि क्या अंतर एक निश्चित सीमा से ऊपर है। आपके मामले में 2 मानों के बीच का अंतर बहुत कम है, जो आपके द्वारा परिभाषित सीमा के नीचे मधुमक्खी पालन कर सकता है।
योहन ओबदिया

41

यदि वे सभी संख्यात्मक मान हैं तो यदि टोल आपकी सहिष्णुता है ...

all( abs(y - mean(y)) < tol ) 

आपकी समस्या का समाधान है।

संपादित करें:

इसे देखने के बाद, और अन्य उत्तर, और कुछ चीजों को बेंचमार्क करने के बाद DWIN उत्तर के रूप में दो बार तेजी से निकलता है।

abs(max(x) - min(x)) < tol

यह आश्चर्यजनक रूप से थोड़ा तेज है diff(range(x))क्योंकि दो संख्याओं diffसे अधिक -और अलग नहीं होना चाहिए abs। सीमा का अनुरोध न्यूनतम और अधिकतम प्राप्त करने का अनुकूलन करना चाहिए। दोनों diffऔर rangeआदिम कार्य हैं। लेकिन समय झूठ नहीं है।


क्या आप इसके द्वारा विभाजित करने की तुलना में औसत से घटाव के सापेक्ष गुणों पर टिप्पणी कर सकते हैं?
हैडली

यह कम्प्यूटेशनल रूप से सरल है। सिस्टम पर निर्भर करता है, और आर कैसे संकलित और सदिश किया जाता है, इसे कम बिजली की खपत के साथ तेजी से पूरा किया जाएगा। इसके अलावा, जब आप इस अर्थ से विभाजित करते हैं कि आपका परीक्षित परिणाम 1 के सापेक्ष है जबकि घटाव के साथ यह 0 है, जो मुझे अच्छा लगता है। इसके अलावा, सहिष्णुता की अधिक सरल व्याख्या है।
जॉन

1
लेकिन यह इतना भी नहीं है कि विभाजन जटिल है क्योंकि सीमा को निकालने के लिए आवश्यक खोज और सॉर्ट एक साधारण घटाव की तुलना में अधिक कम्प्यूटेशनल रूप से महंगा है। मैंने इसका परीक्षण किया और उपरोक्त कोड जीरो_रेंज फंक्शन हैडली से लगभग 10 गुना तेज है (और आपका जवाब यहां सबसे तेज सही उत्तर के बारे में है)। डिर्क की तुलनात्मक रूप से कार्य धीमी गति से होता है। यह यहाँ का सबसे तेज़ उत्तर है।
जॉन

बस आपके जवाब में जोश की टाइमिंग की टिप्पणियों को देखा है हेडली ... मुझे ऐसी कोई भी स्थिति नहीं मिली है, जहां जीरो_रेंज तेज हो। विसंगति थोड़ा तेज (शायद 20%) के बीच है 10x हमेशा पक्ष में अगर यह जवाब। इसने कई तरीकों की कोशिश की।
जॉन

24
> isTRUE(all.equal( max(y) ,min(y)) )
[1] TRUE
> isTRUE(all.equal( max(x) ,min(x)) )
[1] FALSE

इसी तर्ज पर एक और:

> diff(range(x)) < .Machine$double.eps ^ 0.5
[1] FALSE
> diff(range(y)) < .Machine$double.eps ^ 0.5
[1] TRUE

मुझे नहीं लगता कि यह बहुत कम संख्या के लिए इतनी अच्छी तरह से काम करता है:x <- seq(1, 10) / 1e10
हैडली

2
@ हडले: ओपी ने एक समाधान के लिए कहा, जो सहिष्णुता के विनिर्देशन की अनुमति देगा, क्योंकि संभवतः वह बहुत छोटे अंतरों की परवाह नहीं करता था। all.equal का उपयोग अन्य सहिष्णुता के साथ किया जा सकता है और ओपी इसे समझने लगता है।
IRTFM

2
मैंने खुद को बहुत स्पष्ट रूप से व्यक्त नहीं किया - मेरे उदाहरण में सबसे बड़ी और सबसे छोटी संख्या के बीच दस गुना सापेक्ष अंतर है। शायद यही कुछ आप नोटिस करना चाहते हैं! मुझे लगता है कि आंकड़ों की सीमा के सापेक्ष संख्यात्मक सहिष्णुता की गणना करने की आवश्यकता है - मैंने अतीत में ऐसा नहीं किया है और इससे समस्याएं पैदा हुई हैं।
हेली

2
मुझे नहीं लगता कि मैं आपको सबसे गलत समझ रहा हूं। मुझे लगा कि प्रश्नकर्ता एक समाधान के लिए पूछ रहा था जो प्रभावी रूप से शून्य होने वाली संख्या के लिए दस गुना सापेक्ष अंतर को अनदेखा करेगा। मैंने उसे एक समाधान के लिए पूछने के रूप में सुना जो 1e-11 और 1e-13 के बीच के अंतर को अनदेखा करेगा।
IRTFM

5
मैं कोशिश करता हूं और लोगों को वह देता हूं जिसकी उन्हें आवश्यकता है, न कि वे क्या चाहते हैं;) लेकिन बिंदु लिया गया।
हैली

16

आप उपयोग कर सकते हैं identical()और all.equal()पहले तत्व की सभी अन्य लोगों से तुलना करके, प्रभावी रूप से तुलना को पार कर सकते हैं:

R> compare <- function(v) all(sapply( as.list(v[-1]), 
+                         FUN=function(z) {identical(z, v[1])}))
R> compare(x)
[1] FALSE
R> compare(y)
[1] TRUE
R> 

इस तरह आप किसी भी एप्सिलॉन को identical()आवश्यकतानुसार जोड़ सकते हैं ।


2
हालाँकि यह बहुत ही अयोग्य है ... (मेरे कंप्यूटर पर यह एक मिलियन की संख्या के लिए लगभग 10 सेकंड का समय लेता है)
हैडली

2
इसमें कोई शक नहीं। ओपी हालांकि पूछताछ की गई थी इस किया जा सकता है कि क्या सब पर । इसे अच्छी तरह से करना एक दूसरा कदम है। और आप जानते हैं कि मैं छोरों के साथ कहां खड़ा हूं
?;

10
कि छोरों कमाल कर रहे हैं? ;)
हैडली

4
इस एपॉच के बारे में मुझे जो पसंद है वह यह है कि इसका उपयोग गैर-संख्यात्मक वस्तुओं के साथ किया जा सकता है।
लुसियानो सेल्जर

तुलना <- फ़ंक्शन (v) सभी (sapply (as.list (v [-1]), FUN = function (z) {isTRUE (all.equal (z, v [1]))))
N. McA ।

16

आप बस चेक कर सकते हैं all(v==v[1])


यह एक महान बीसी है यह तार के साथ भी काम करता है! धन्यवाद
arvi1000

यह तब तक काम करता है जब तक आप NAअपने वेक्टर में नहीं होते: x <- c(1,1,NA); all(x == x[1])रिटर्न NA, नहीं FALSE। ऐसे मामलों में length(unique(x)) == 1काम करता है।
HBAT

11

चूँकि मैं इस सवाल पर बार-बार आ रहा हूँ, यहाँ एक Rcppसमाधान है जो आम तौर पर किसी भी Rसमाधान की तुलना में बहुत तेज़ होगा यदि उत्तर वास्तव में है FALSE(क्योंकि यह उस क्षण को एक बेमेल का सामना करना बंद कर देगा) और उसी गति से होगा सबसे तेजी से आर समाधान के रूप में अगर जवाब है TRUE। ओपी बेंचमार्क के लिए उदाहरण के लिए, system.timeइस फ़ंक्शन का उपयोग करके ठीक 0 पर घड़ियों।

library(inline)
library(Rcpp)

fast_equal = cxxfunction(signature(x = 'numeric', y = 'numeric'), '
  NumericVector var(x);
  double precision = as<double>(y);

  for (int i = 0, size = var.size(); i < size; ++i) {
    if (var[i] - var[0] > precision || var[0] - var[i] > precision)
      return Rcpp::wrap(false);
  }

  return Rcpp::wrap(true);
', plugin = 'Rcpp')

fast_equal(c(1,2,3), 0.1)
#[1] FALSE
fast_equal(c(1,2,3), 2)
#[2] TRUE

1
यह गति के लिए अच्छा और +1 है, लेकिन मैं आश्वस्त नहीं हूं कि सभी तत्वों की तुलना 1 तत्व से करना काफी सही है। एक वेक्टर इस परीक्षा को पास कर सकता है, फिर भी अधिकतम (x) और मिनट (x) के बीच का अंतर सटीक से अधिक होना चाहिए। उदाहरण के लिएfast_equal(c(2,1,3), 1.5)
dww

@dww आप जो इंगित कर रहे हैं, वह यह है कि जब आप सटीक मुद्दे हैं a == b, तो तुलनात्मक रूप से तुलनात्मक b == cनहीं है - a == cयदि आप फ्लोटिंग पॉइंट की तुलना कर रहे हैं, तो जरूरी नहीं है । आप या तो इस समस्या से बचने के लिए तत्वों की संख्या के आधार पर आपके सटीक विभाजित कर सकते हैं, या एल्गोरिथ्म गणना करने के लिए संशोधित minऔर maxहै कि एक रोक शर्त के रूप में और इस्तेमाल करते हैं।
इडली

10

मैंने इसके लिए विशेष रूप से एक फ़ंक्शन लिखा, जो न केवल एक वेक्टर में तत्वों की जांच कर सकता है, बल्कि यह भी जांचने में सक्षम है कि किसी सूची के सभी तत्व समान हैं या नहीं । बेशक यह अच्छी तरह से चरित्र वैक्टर और अन्य सभी प्रकार के वेक्टर को अच्छी तरह से संभालता है। इसमें उपयुक्त त्रुटि हैंडलिंग भी है।

all_identical <- function(x) {
  if (length(x) == 1L) {
    warning("'x' has a length of only 1")
    return(TRUE)
  } else if (length(x) == 0L) {
    warning("'x' has a length of 0")
    return(logical(0))
  } else {
    TF <- vapply(1:(length(x)-1),
                 function(n) identical(x[[n]], x[[n+1]]),
                 logical(1))
    if (all(TF)) TRUE else FALSE
  }
}

अब कुछ उदाहरणों की कोशिश करते हैं।

x <- c(1, 1, 1, NA, 1, 1, 1)
all_identical(x)       ## Return FALSE
all_identical(x[-4])   ## Return TRUE
y <- list(fac1 = factor(c("A", "B")),
          fac2 = factor(c("A", "B"), levels = c("B", "A"))
          )
all_identical(y)     ## Return FALSE as fac1 and fac2 have different level order

4

आपको वास्तव में न्यूनतम, मीन या अधिकतम का उपयोग करने की आवश्यकता नहीं है। जॉन के जवाब पर आधारित:

all(abs(x - x[[1]]) < tolerance)

3

यहां मिन का उपयोग कर एक विकल्प, अधिकतम चाल लेकिन एक डेटा फ्रेम के लिए। उदाहरण में मैं स्तंभों की तुलना कर रहा हूं, लेकिन applyपंक्तियों के लिए मार्जिन पैरामीटर को 1 में बदला जा सकता है।

valid = sum(!apply(your_dataframe, 2, function(x) diff(c(min(x), max(x)))) == 0)

यदि है valid == 0तो सभी तत्व समान हैं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.