একটি একক ভেক্টরের সমস্ত উপাদানগুলির মধ্যে সমতার জন্য পরীক্ষা


103

আমি ভেক্টরের সমস্ত উপাদান একে অপরের সমান কিনা তা পরীক্ষার চেষ্টা করছি। আমি যে সমাধানগুলি নিয়ে এসেছি সেগুলি কিছুটা চতুর্দিকের মনে হয়, উভয়ই চেক জড়িত 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))
}

আপনি যদি আরও গুরুত্ব সহকারে এটি ব্যবহার করছিলেন তবে আপনি সম্ভবত পরিসীমাটি গণনার আগে অনুপস্থিত মানগুলি মুছে ফেলতে চাইবেন।


এটিকে আমি ডার্কের চেয়ে দ্রুত হওয়ার জন্য বেছে নিয়েছি। আমার কয়েক মিলিয়ন উপাদান নেই, তবে এটি আমার জন্য আরও দ্রুত চালানো উচিত।
কিমিমি

@ কেভিন: জন এর সমাধান সম্পর্কে কি? এটি হ্যাডলির তুলনায় x 10x দ্রুত এবং আপনাকে সহনশীলতা সেট করতে দেয়। অন্য কোনও উপায়ে কি এর ঘাটতি?
জোশুয়া উলিরিচ

দয়া করে কিছু বেঞ্চমার্কিং সরবরাহ করুন - আমি সন্ধান করেছি আমার মিলিয়ন ইউনিফর্মের ভেক্টরের জন্য প্রায় একই রকম।
হ্যাডলি

@ হ্যাডলি: আমি দৌড়াচ্ছিলাম system.time(for(i in 1:1e4) zero_range(x)), xওপি থেকে কোথায় ছিলাম। জন এর দ্রবণটি 10 ​​ডলার x, ~ 3x দ্রুত yএবং সামান্য ধীর runif(1e6)
জোশুয়া উলিরিচ

আপনি যখন 0.00023 এবং 0.000023 সেকেন্ডের মধ্যে পার্থক্যটি দেখছেন তখন 10x পার্থক্য খুব বেশি গুরুত্বপূর্ণ নয় - এবং ডিউইন সম্ভবত দাবি করবেন যে তারা নির্ধারিত সহনশীলতার সাথে একই রকম;)
হ্যাডলি

48

কেন কেবল প্রকরণটি ব্যবহার করা হচ্ছে না:

var(x) == 0

সমস্ত উপাদান xসমান হলে, আপনি একটি বৈকল্পিক পাবেন 0


18
length(unique(x))=1প্রায় দ্বিগুণ দ্রুত গতিতে শেষ হয়, তবে varএটি নিখরচায় which
আদমো

যোহানবাদিয়া, আমার কাছে একটি অ্যারে সি রয়েছে (-5.532456e-09, 1.695298e-09), এবং John test: TRUE ; DWin test: TRUE ; zero-range test: TRUE ; variance test: FALSEঅন্যান্য সমস্ত পরীক্ষার অর্থ পেয়ে যায় যে মানগুলি আরে অভিন্ন। সেই প্রসঙ্গে কীভাবে বৈকল্পিক পরীক্ষাটি ব্যবহার করা যেতে পারে?
এমজেএস

আপনার অ্যারেতে থাকা 2 টি মান একরকম নয়। আপনি কেন পরীক্ষা ফিরে চান TRUE? জন এর উত্তরের ক্ষেত্রে, আপনি পার্থক্যটি একটি নির্দিষ্ট প্রান্তিকের চেয়ে উপরে কিনা তা পরীক্ষা করে দেখুন। আপনার ক্ষেত্রে 2 টি মানের মধ্যে পার্থক্য খুব কম, এটি আপনার সংজ্ঞায়িত প্রান্তিকের নীচে মৌমাছি হতে পারে।
যোহান ওবাদিয়া

41

যদি সেগুলি সমস্ত সংখ্যাসূচক মান হয় তবে যদি টোলটি আপনার সহনশীলতা হয় তবে ...

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

আপনার সমস্যার সমাধান your

সম্পাদনা:

এটি এবং অন্যান্য উত্তরগুলি দেখার পরে এবং কয়েকটি বিষয় বেঞ্চমার্ক করার পরে ডিউইন উত্তর হিসাবে দ্বিগুণ দ্রুত নীচে প্রকাশিত হবে।

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

এটি কিছুক্ষণ আশ্চর্যজনক চেয়ে দ্রুত diff(range(x))যেহেতু diffতুলনায় অনেক বিভিন্ন থাকা উচিত নয় -এবং absদুটি সংখ্যার সাথে। সীমাটির অনুরোধ করা সর্বনিম্ন এবং সর্বাধিক প্রাপ্তিকে অনুকূলিত করা উচিত। উভয় diffএবং rangeআদিম ফাংশন। কিন্তু সময় মিথ্যা না।


আপনি এটির সাথে ভাগ করার তুলনায় গড়কে বিয়োগ করার তুলনামূলক গুণাবলী সম্পর্কে মন্তব্য করতে পারেন?
হ্যাডলি

এটি গণনামূলকভাবে সহজ। সিস্টেমের উপর নির্ভর করে, এবং কীভাবে আর সংকলন এবং ভেক্টরাইজ করা হয়, এটি কম বিদ্যুত ব্যবহারের সাথে দ্রুত সম্পন্ন হবে। এছাড়াও, আপনি যখন গড় দিয়ে ভাগ করবেন তখন আপনার পরীক্ষিত ফলাফল 1 এর সাথে তুলনামূলকভাবে বিয়োগের সাথে 0 হয়, যা আমার কাছে ভাল লাগে। এছাড়াও, সহনশীলতার আরও সরল ব্যাখ্যা রয়েছে।
জন

4
তবে এটি এতোটুকুও নয় যে বিভাগটি জটিল, কারণ পরিসীমাটি বের করতে প্রয়োজনীয় অনুসন্ধান এবং বাছাই একটি সাধারণ বিয়োগফলের চেয়ে অনেক বেশি গণনামূলক ব্যয়বহুল। আমি এটি পরীক্ষা করেছি এবং উপরের কোডটি শূন্য_আরঞ্জ ফাংশন হ্যাডলির চেয়ে প্রায় 10x দ্রুত (এবং আপনার এখানে দ্রুততম সঠিক উত্তরটি রয়েছে)। ডার্কের তুলনা কার্যটি নির্মমভাবে ধীর। এটি এখানে দ্রুততম উত্তর।
জন

আপনার উত্তরে হ্যাডলির জোশের সময়কালীন মন্তব্যগুলি দেখেছি ... আমি শূন্য_আরঞ্জ দ্রুততর কোনও পরিস্থিতি পাই না। এই উত্তরটি যদি সামান্য দ্রুত হয় (তবে 20%) থেকে 10x এর মধ্যে সর্বদা পক্ষে থাকে always এটি অনেকগুলি পদ্ধতি চেষ্টা করেছিল।
জন

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
হ্যাডলি

4
@ হ্যাডলি: ওপি এমন একটি সমাধান চেয়েছিল যা সহনশীলতার নির্দিষ্টকরণের অনুমতি দেয়, সম্ভবতঃ তিনি খুব সামান্য পার্থক্যের বিষয়ে চিন্তা করেননি। all.equal অন্যান্য সহনশীলতার সাথে ব্যবহার করা যেতে পারে এবং ওপি এটি বুঝতে পারে।
আইআরটিএফএম

4
আমি নিজেকে খুব স্পষ্টভাবে প্রকাশ করিনি - আমার উদাহরণে সবচেয়ে বড় এবং ক্ষুদ্রতম সংখ্যার মধ্যে দশগুণ আপেক্ষিক পার্থক্য রয়েছে। এটি সম্ভবত আপনি লক্ষ্য করতে চান এমন কিছু! আমি মনে করি সংখ্যার সহনশীলতাটি ডেটাগুলির পরিসরের তুলনায় গণনা করা দরকার - আমি অতীতে এটি করি নি এবং এটি সমস্যার সৃষ্টি করেছে।
হ্যাডলি

4
আমি মনে করি না যে আমি আপনাকে সবচেয়ে ভুল বুঝেছি। আমি কেবল ভেবেছিলাম যে প্রশ্নকারী এমন একটি সমাধান চেয়েছিলেন যা কার্যকরভাবে শূন্যের সংখ্যার জন্য দশগুণ আপেক্ষিক পার্থক্য উপেক্ষা করবে। আমি তাকে এমন সমাধানের অনুরোধ করতে শুনেছি যা 1e-11 এবং 1e-13 এর মধ্যে পার্থক্যটিকে উপেক্ষা করবে।
আইআরটিএফএম

5
আমি চেষ্টা করি এবং লোকেরা তাদের যা প্রয়োজন তা দেয়, তারা যা চায় তা নয়;) তবে পয়েন্ট নিয়েছে।
হ্যাডলি

19

আপনি ঠিক পরীক্ষা করতে পারেন all(v==v[1])


এটি একটি দুর্দান্ত বিসি এটি স্ট্রিংগুলির সাথেও কাজ করে! ধন্যবাদ
arvi1000

4
NAআপনার ভেক্টরে না থাকলে এটি কাজ করে : x <- c(1,1,NA); all(x == x[1])ফিরে আসে NA, না FALSE। এ জাতীয় ক্ষেত্রে length(unique(x)) == 1কাজ করে।
এইচবিট

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()প্রয়োজন হিসাবে কোনও অ্যাপসিলন যুক্ত করতে পারেন ।


4
যদিও পুরোপুরি অক্ষম ... (আমার কম্পিউটারে এটি এক মিলিয়ন সংখ্যার জন্য প্রায় 10 সেকেন্ড সময় নেয়)
হ্যাডলি

4
কোনো সন্দেহ নেই. ওপি তবে জিজ্ঞাসাবাদ করা হয় এই কাজ করা যাবে কিনা এ সব । এটি ভালভাবে করা দ্বিতীয় পদক্ষেপ। এবং আপনি জানেন যে আমি কোথায় লুপগুলি নিয়ে দাঁড়িয়ে আছি ... ;-)
ডার্ক এডেলবুয়েটেল

10
লুপগুলি কি দুর্দান্ত? ;)
হ্যাডলি

4
আমি এই অ্যাপোচ সম্পর্কে যা পছন্দ করি তা হ'ল এটি অ সংখ্যাসূচক অবজেক্টের সাথে ব্যবহার করা যেতে পারে।
লুসিয়ানো সেলজার

<- ফাংশন (ভি) সমস্ত (সাপ্লাই (as.list (v [-1]), FUN = ফাংশন (z) T isTRUE (all.equal (z, v [1])}))
তুলনা করুন

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

4
এটি গতির পক্ষে & +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সমস্ত উপাদান একই হয়

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.