ভেক্টর বা কলামে সেকেন্ডের (তৃতীয়…) সর্বাধিক / সর্বনিম্ন মান সন্ধানের দ্রুততম উপায়


161

আর সর্বোচ্চ এবং সর্বনিম্ন অফার দেয় তবে পুরো ভেক্টরটিকে বাছাই করা এবং এই ভেক্টর থেকে মান x বাছাইয়ের পরিবর্তে ক্রমে অন্য মানটি খুঁজে পাওয়ার সত্যিই দ্রুত উপায় আমি দেখতে পাই না।

দ্বিতীয় সর্বোচ্চ মান (উদাঃ) পাওয়ার জন্য কি আরও দ্রুত উপায় আছে?

ধন্যবাদ


Cran উপর প্যাকেজ কিট টি topnফাংশন যা চেয়ে দ্রুত sort, orderএবং nth। ডকুমেন্টেশন দেখুন।
সুরেশ_প্যাটেল

উত্তর:


195

এর partialযুক্তিটি ব্যবহার করুন sort()। দ্বিতীয় সর্বোচ্চ মানের জন্য:

n <- length(x)
sort(x,partial=n-1)[n-1]

4
sort(x, TRUE)[2]@ আবরারের উত্তরে বর্ণিত বর্ণনার বিপরীতে এই পদ্ধতির কী কী সুবিধা রয়েছে , প্রশ্নটিতে সীমাবদ্ধতা না মেটানো ছাড়া?
হিউ

5
আমি এই পদ্ধতিটি ব্যবহার করেছি, তবে নিম্নলিখিত ত্রুটিটি পেয়েছি: Error in sort.int(x, na.last = na.last, decreasing = decreasing, ...) : index 4705 outside bounds সমস্যাটি কী হতে পারে কোনও ধারণা? কিছু বিশদ: আমার এক্স দৈর্ঘ্যের একটি দৈনিক ভেক্টর 4706 NAএর ডেটাতে কিছু গুলি with আমি @ রবহাইন্ডম্যানের পরামর্শ অনুসারে ঠিক একই কোডটি ব্যবহার করে ভেক্টরে দ্বিতীয় সর্বোচ্চ মান পাওয়ার চেষ্টা করেছি।
শ্রীরামন

আপনি কেন উত্থানকে বাছাই করে এবং কেবলমাত্র দুটি মানের দ্বিতীয়টি গ্রহণ করেন না? এটি কি দ্রুত হবে না?
jwg

3
বর্ণনামূলক যুক্তি আংশিক বাছাইয়ের সাথে সামঞ্জস্যপূর্ণ নয়।
রব হ্যান্ডম্যান

7
যদিও decreasingআর্গুমেন্ট আংশিক বাছাইয়ের সাথে সামঞ্জস্য নয়, আপনি সর্বদা পারেন -sort(-x, partial=n-1)[n-1]; এটি যৌক্তিকভাবে একই জিনিস এবং তুলনায় যথেষ্ট কম সময় নেয় sort(x, decreasing=TRUE)[n-1]
r2evans

52

সামান্য ধীর বিকল্প, কেবল রেকর্ডগুলির জন্য:

x <- c(12.45,34,4,0,-234,45.6,4)
max( x[x!=max(x)] )
min( x[x!=min(x)] )

এটি পুরো ভেক্টরকে বাছাই করা এবং এন -1 ম মান গ্রহণের চেয়ে যদি আরও দ্রুত হয় তবে অবাক লাগবে!
jwg

@jwg এটি ও (এন) তাই এটি বড় ডেটাসেটে বাছাই করার চেয়ে দ্রুত হওয়া উচিত।
Museful

অন্যান্য গৃহীত উত্তরের চেয়ে এনএর সাথে আরও ভাল কাজ করে - 'মিনিট' ফাংশনের আর্গুমেন্ট হিসাবে কেবল 'na.rm = TRUE' ব্যবহার করুন।
ইয়ার দাওন

2
আমার কাছে মনে হচ্ছে আপনি একটি ছোট পরিবর্তন দিয়ে কিছুটা গতির উন্নতি পেতে পারেন:max(x[-which.max(x)])
সিন্ড্রি_বলদুর

31

আমি রবের উত্তরটিকে আরও কিছুটা সাধারণ ফাংশনে গুটিয়ে রেখেছি, যা দ্বিতীয়, তৃতীয়, চতুর্থ (ইত্যাদি) সর্বাধিক সন্ধান করতে ব্যবহার করা যেতে পারে:

maxN <- function(x, N=2){
  len <- length(x)
  if(N>len){
    warning('N greater than length(x).  Setting N=length(x)')
    N <- length(x)
  }
  sort(x,partial=len-N+1)[len-N+1]
}

maxN(1:10)

1
কুল। এই ব্যবহারটি বিশেষভাবে কার্যকর maxN(1:10, 1:3)(আমি ডিফল্ট N তে 1 সেট করে দিতাম)
প্যাট্রিকটি

23

প্রাতঃরাশের nth_element নামে একটি ফাংশন রয়েছে যা আপনি যা চান তা ঠিকভাবে করে এবং উপরে বর্ণিত সমস্ত বাস্তবায়নের চেয়ে দ্রুত

এছাড়াও উপরোক্ত আলোচিত পদ্ধতিগুলি যা আংশিক বাছাইয়ের উপর ভিত্তি করে, কে ক্ষুদ্রতম মানগুলি সন্ধান করার পক্ষে সমর্থন করে না

Rfast::nth(x, 5, descending = T)

X এর 5 তম বৃহত্তম উপাদানটি ফিরিয়ে দেবে, যখন while

Rfast::nth(x, 5, descending = F)

X এর 5 তম ক্ষুদ্রতম উপাদানটি ফেরত দেবে

সর্বাধিক জনপ্রিয় উত্তরের বিপরীতে বেনমার্কগুলি।

10 হাজার সংখ্যার জন্য:

N = 10000
x = rnorm(N)

maxN <- function(x, N=2){
    len <- length(x)
    if(N>len){
        warning('N greater than length(x).  Setting N=length(x)')
        N <- length(x)
    }
    sort(x,partial=len-N+1)[len-N+1]
}

microbenchmark::microbenchmark(
    Rfast = Rfast::nth(x,5,descending = T),
    maxn = maxN(x,5),
    order = x[order(x, decreasing = T)[5]]
)

Unit: microseconds
  expr      min       lq      mean   median        uq       max neval
 Rfast  160.364  179.607  202.8024  194.575  210.1830   351.517   100
  maxN  396.419  423.360  559.2707  446.452  487.0775  4949.452   100
 order 1288.466 1343.417 1746.7627 1433.221 1500.7865 13768.148   100

1 মিলিয়ন সংখ্যার জন্য:

N = 1e6 #evaluates to 1 million
x = rnorm(N)

microbenchmark::microbenchmark(
    Rfast = Rfast::nth(x,5,descending = T),
    maxN = maxN(x,5),
    order = x[order(x, decreasing = T)[5]]
)

Unit: milliseconds
  expr      min        lq      mean   median        uq       max neval
 Rfast  89.7722  93.63674  114.9893 104.6325  120.5767  204.8839   100
  maxN 150.2822 207.03922  235.3037 241.7604  259.7476  336.7051   100
 order 930.8924 968.54785 1005.5487 991.7995 1031.0290 1164.9129   100

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

3
এটি উল্লেখ করে যে Rfast::nthএকাধিক উপাদান (যেমন 8 ম এবং 9 ম বৃহত্তম উপাদান) পাশাপাশি সেই উপাদানগুলির সূচকগুলিও ফিরে আসতে পারে।
জশা 18

3
প্রাতঃরাশের সমাধান সম্পর্কে আমি যা পছন্দ করি তা হ'ল প্রতিটি সারি বা কলামের জন্য এটি করার জন্য প্যাকেজের একটি সহজেই কার্যকর সমাধান রয়েছে।
জয়

16

এখানে কোনও ভেক্টরের এন সবচেয়ে ক্ষুদ্রতম / বৃহত্তম মানগুলির সূচকগুলি খুঁজে পাওয়ার একটি সহজ উপায় এখানে রয়েছে (এন = 3 এর উদাহরণ):

N <- 3

সবচেয়ে ছোট:

ndx <- order(x)[1:N]

সবচেয়ে বড়:

ndx <- order(x, decreasing = T)[1:N]

সুতরাং আপনি মানগুলি যেমনটি বের করতে পারেন:

x[ndx]

এটি এল লগ এল সময়ে চলবে, যেখানে এল এর দৈর্ঘ্য is আমি মনে করি ব্যবহারকারী লগ এল সময়ে চালিত এমন কোনও পদ্ধতির প্রত্যাশা করেছিল।
আর্সমথ

যদি পদ্ধতিগুলি সময় অনুসারে অর্ডার করা হয় এবং দ্রুততম এন বের করা হয় তবে এটি দ্বিতীয় দ্রুততম উপায় হতে পারে। আমি এটিও পছন্দ করি কারণ এটি গৃহীত সমাধানের তুলনায় খুব স্পষ্ট কোড।
পিট

1
তাত্ত্বিক সেরা এবং স্বীকৃত পদ্ধতি (আশাবাদী) হে (লগ এল) নয়, ও (এল) সময়ে চলে। এটি ও (লগ ল) এ চলে L
ভ্যালেন্টাস 14'18

6

নবম সর্বোচ্চ মানের জন্য,

sort(x, TRUE)[n]

8
ওপি ইতিমধ্যে তার পোস্টে বলেছে যে এটি এমন একটি সমাধান যা তিনি ব্যবহার করতে চান না: "পুরো ভেক্টরকে বাছাই করা এবং এই ভেক্টর থেকে মান x বাছাইয়ের চেয়ে"।
পল হিমস্ট্র্রা

3

আমি দেখেছি যে সর্বাধিক উপাদানটি সরানো এবং তারপরে তুলনীয় গতিতে আরও একটি সর্বোচ্চ রান করা:

system.time({a=runif(1000000);m=max(a);i=which.max(a);b=a[-i];max(b)})
   user  system elapsed 
  0.092   0.000   0.659 

system.time({a=runif(1000000);n=length(a);sort(a,partial=n-1)[n-1]})
   user  system elapsed 
  0.096   0.000   0.653 

2

এখানে আমি খুঁজে পেয়েছি সবচেয়ে সহজ উপায়,

num <- c(5665,1615,5154,65564,69895646)

num <- sort(num, decreasing = F)

tail(num, 1)                           # Highest number
head(tail(num, 2),1)                   # Second Highest number
head(tail(num, 3),1)                   # Third Highest number
head(tail(num, n),1)                   # Generl equation for finding nth Highest number

1

আমি সম্প্রতি একটি খুঁজছেন ছিল যখন আর একটি প্রদত্ত ভেক্টর শীর্ষ এন সর্বোচ্চ / মিনিট সংখ্যার সূচী ফিরে ফাংশন, আমি তো শুনে এমন কোন একটি ফাংশন আছে।

এবং এটি খুব অনুরূপ কিছু।

বেস :: অর্ডার ফাংশনটি ব্যবহার করে ব্রুট ফোর্স সলিউশনটি সবচেয়ে সহজ বলে মনে হচ্ছে।

topMaxUsingFullSort <- function(x, N) {
  sort(x, decreasing = TRUE)[1:min(N, length(x))]
}

আপনার ভেক্টরের এক্স দৈর্ঘ্যের তুলনায় আপনার এন মান তুলনামূলকভাবে ছোট হওয়ার ক্ষেত্রে এটি দ্রুততম নয় ।

অন্যদিকে যদি এন সত্যিই ছোট হয় তবে আপনি বেসটি ব্যবহার করতে পারেন : যা ম্যাক্সটি পুনরাবৃত্তভাবে ফাংশন করে এবং প্রতিটি পুনরাবৃত্তিতে আপনি প্রাপ্ত মানটি -আইএনএফ দ্বারা প্রতিস্থাপন করতে পারেন

# the input vector 'x' must not contain -Inf value 
topMaxUsingWhichMax <- function(x, N) {
  vals <- c()
  for(i in 1:min(N, length(x))) {
    idx      <- which.max(x)
    vals     <- c(vals, x[idx]) # copy-on-modify (this is not an issue because idxs is relative small vector)
    x[idx]   <- -Inf            # copy-on-modify (this is the issue because data vector could be huge)
  }
  vals
}

আমি বিশ্বাস করি আপনি সমস্যাটি দেখেছেন - অনুলিপিটির অনুলিপি আর। সুতরাং এটি খুব খুব ছোট এন (1,2,3) এর জন্য আরও ভাল পারফর্ম করবে তবে এটি বৃহত্তর এন মানগুলির জন্য দ্রুত কমবে। এবং আপনি ভেক্টর এক্স এন বারের সমস্ত উপাদানগুলিতে পুনরাবৃত্তি করছেন ।

আমি মনে করি পরিষ্কার সবচেয়ে ভালো সমাধান আর আংশিক ব্যবহার করা বেস :: সাজানোর

topMaxUsingPartialSort <- function(x, N) {
  N <- min(N, length(x))
  x[x >= -sort(-x, partial=N)[N]][1:N]
}

তারপরে আপনি উপরের ডিফল্ট ফাংশনগুলির ফলাফল থেকে শেষ ( এন ম) আইটেমটি নির্বাচন করতে পারেন ।

দ্রষ্টব্য: উপরে বর্ণিত ফাংশনগুলি কেবল উদাহরণ - আপনি যদি সেগুলি ব্যবহার করতে চান তবে আপনাকে চেক / স্যানিটি ইনপুটগুলি (যেমন, এন> দৈর্ঘ্য (এক্স) ) পরীক্ষা করতে হবে।

আমি খুব অনুরূপ কিছু সম্পর্কে একটি ছোট্ট নিবন্ধ লিখেছিলাম (ভেক্টরের শীর্ষ এন সর্বাধিক / মিনিটের মানগুলির সূচি পান) http://palusga.cz/?p=18 - আপনি এখানে বর্ণিত অনুরূপ ফাংশনগুলির কয়েকটি মানদণ্ড খুঁজে পেতে পারেন।



0
topn = function(vector, n){
  maxs=c()
  ind=c()
  for (i in 1:n){
    biggest=match(max(vector), vector)
    ind[i]=biggest
    maxs[i]=max(vector)
    vector=vector[-biggest]
  }
  mat=cbind(maxs, ind)
  return(mat)
}

এই ফাংশনটি শীর্ষ এন মানগুলি এবং তাদের সূচকগুলি সহ একটি ম্যাট্রিক্স ফিরিয়ে দেবে। আশা করি এটি ভিদেবী-চৌকে সহায়তা করবে


0

এটি ইনপুট সংখ্যা ভেক্টর এক্স এর N'th ক্ষুদ্রতম বা বৃহত্তম মানের সূচকটি খুঁজে পাবে। নীচের দিক থেকে N'th চাইলে আর্গুমেন্টে নীচে = সত্য নির্ধারণ করুন, অথবা উপরে থেকে N'th চাইলে নীচে = FALSE করুন। এন = 1 এবং নীচে = সত্য, সমান যা.মিন, এন = 1 এবং নীচে = ফলস যা.ম্যাক্সের সমান।

FindIndicesBottomTopN <- function(x=c(4,-2,5,-77,99),N=1,bottom=FALSE)
{

  k1 <- rank(x)
  if(bottom==TRUE){
    Nindex <- which(k1==N)
    Nindex <- Nindex[1]
  }

  if(bottom==FALSE){
    Nindex <- which(k1==(length(x)+1-N))
    Nindex <- Nindex[1]
  }

  return(Nindex)
}

0

dplyr এর nth ফাংশন রয়েছে, যেখানে প্রথম আর্গুমেন্টটি ভেক্টর এবং দ্বিতীয়টি আপনি চান কোন জায়গাটি। এটি পাশাপাশি পুনরাবৃত্তি উপাদান জন্য যায়। উদাহরণ স্বরূপ:

x = c(1,2, 8, 16, 17, 20, 1, 20)

দ্বিতীয় বৃহত্তম মান সন্ধান করা:

 nth(unique(x),length(unique(x))-1)

[1] 17

2
এই দ্রুত ...?
বেন বলকার

2
অভ্যন্তরীণভাবে এটি ব্যবহার করে x[[order(order_by)[[n]]]]- সুতরাং এটির পুরো ভেক্টর বাছাই করা প্রয়োজন। সুতরাং এটি গৃহীত উত্তরের মতো দ্রুত হবে না।
বেন বলকার

5
তবে এটি sort আংশিক = যুক্তি (যা সবকিছু পরিবর্তন করে) দিয়ে ব্যবহার করে
বেন বলকার

@ বেনবোলকার যা পাওলো বা রবের উত্তর বোঝায় তাতে উন্নতি করতে ব্যবহার করা যেতে পারে dplyr::nth()? bench::mark(max(x[-which.max(x)]), x[[order(-x)[[2]]]] ), nth()প্রায় 10 গুণ ধীর বলে মনে হচ্ছে যেখানে length(x)3 মিলিয়ন।
সিন্ড্রি_বালদুর

-1

আপনি পরবর্তী উচ্চতর মানটি সনাক্ত করতে পারবেন cummax()। উদাহরণস্বরূপ আপনি যদি প্রতিটি নতুন উচ্চতর মানের অবস্থান চান তবে আপনি যে cummax()মানগুলিতে পরিবর্তন হয়েছে সেগুলি সনাক্ত করতে আপনি আপনার ভেক্টরকে diff()ফাংশনে পাস করতে পারেন cummax()। বলুন আমাদের ভেক্টর আছে

v <- c(4,6,3,2,-5,6,8,12,16)
cummax(v) will give us the vector
4  6  6  6  6  6  8 12 16

এখন, আপনি যদি কোনও পরিবর্তনের অবস্থানটি খুঁজতে চান তবে cummax()আমার কাছে অনেকগুলি বিকল্প রয়েছে sign(diff(cummax(v)))। হারানো প্রথম উপাদানটির জন্য আপনাকে সামঞ্জস্য করতে হবে diff()। ভেক্টরের সম্পূর্ণ কোডটি হ'ল v:

which(sign(diff(cummax(v)))==1)+1

আমি মনে করি আপনি প্রশ্নটি ভুল বুঝেছেন। লক্ষ্যটি হ'ল, বলুন, দ্বিতীয় সর্বোচ্চ মান। কীভাবে এটি আপনাকে ভি থেকে 12 পর্যন্ত পেতে সহায়তা করে ... এবং তৃতীয় সর্বোচ্চ 8 এর জন্য?
ফ্রাঙ্ক

-1

আপনি sortকীওয়ার্ডটি এর মতো ব্যবহার করতে পারেন :

sort(unique(c))[1:N]

উদাহরণ:

c <- c(4,2,44,2,1,45,34,2,4,22,244)
sort(unique(c), decreasing = TRUE)[1:5]

প্রথম 5 সর্বোচ্চ নম্বর দেবে।

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