R เสนอสูงสุดและต่ำสุด แต่ฉันไม่เห็นวิธีที่รวดเร็วจริงๆในการหาค่าอื่นในการสั่งซื้อนอกเหนือจากการจัดเรียงเวกเตอร์ทั้งหมดแล้วเลือกค่า x จากเวกเตอร์นี้
มีวิธีที่เร็วกว่าเพื่อให้ได้ค่าที่สองสูงสุดหรือไม่
R เสนอสูงสุดและต่ำสุด แต่ฉันไม่เห็นวิธีที่รวดเร็วจริงๆในการหาค่าอื่นในการสั่งซื้อนอกเหนือจากการจัดเรียงเวกเตอร์ทั้งหมดแล้วเลือกค่า x จากเวกเตอร์นี้
มีวิธีที่เร็วกว่าเพื่อให้ได้ค่าที่สองสูงสุดหรือไม่
คำตอบ:
ใช้ข้อโต้แย้งของpartial
sort()
สำหรับค่าสูงสุดลำดับที่สอง:
n <- length(x)
sort(x,partial=n-1)[n-1]
sort(x, TRUE)[2]
ที่อธิบายไว้ในคำตอบของ @ Abrar นอกเหนือจากการไม่พอใจข้อ จำกัด ในคำถาม?
Error in sort.int(x, na.last = na.last, decreasing = decreasing, ...) : index 4705 outside bounds
ความคิดใด ๆ ที่อาจเป็นปัญหา รายละเอียดบางอย่าง: x ของฉันคือเวกเตอร์ตัวเลขที่มีความยาว 4706 และมีบางส่วนNA
ในข้อมูล ฉันพยายามรับค่าสูงสุดอันดับสองในเวกเตอร์โดยใช้รหัสเดียวกันตามที่ @RobHyndman แนะนำ
decreasing
การโต้เถียงกันไม่ได้กับการเรียงลำดับบางส่วนที่คุณสามารถเสมอ-sort(-x, partial=n-1)[n-1]
; มันมีเหตุผลเหมือนกันและใช้เวลาน้อยกว่าsort(x, decreasing=TRUE)[n-1]
มาก
ทางเลือกที่ช้าลงเล็กน้อยสำหรับระเบียนเท่านั้น:
x <- c(12.45,34,4,0,-234,45.6,4)
max( x[x!=max(x)] )
min( x[x!=min(x)] )
max(x[-which.max(x)])
ฉันห่อคำตอบของ Rob ไว้ในฟังก์ชั่นทั่วไปที่มากกว่าเล็กน้อยซึ่งสามารถใช้หาค่าสูงสุดที่ 2, 3, 4 (ฯลฯ ):
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)
maxN(1:10, 1:3)
(ฉันจะตั้งค่าเริ่มต้น N เป็น 1)
Rfastมีฟังก์ชั่นที่เรียกว่า nth_element ซึ่งทำสิ่งที่คุณขออย่างแน่นอนและเร็วกว่าการนำไปใช้ทั้งหมดที่กล่าวถึงข้างต้น
ยังมีวิธีการที่กล่าวข้างต้นว่าจะขึ้นอยู่กับการจัดเรียงบางส่วนไม่สนับสนุนการหาเคที่เล็กที่สุดค่า
Rfast::nth(x, 5, descending = T)
จะส่งคืนองค์ประกอบที่ใหญ่ที่สุดอันดับ 5 ของ x ในขณะที่
Rfast::nth(x, 5, descending = F)
จะส่งคืนองค์ประกอบที่เล็กที่สุดที่ 5 ของ x
เปรียบเทียบด้านล่างกับคำตอบที่ได้รับความนิยมมากที่สุด
สำหรับ 10,000 ตัวเลข:
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
Rfast::nth
สามารถส่งคืนองค์ประกอบหลายรายการ (เช่นองค์ประกอบที่ใหญ่ที่สุด 8 และ 9) เช่นเดียวกับดัชนีขององค์ประกอบเหล่านั้น
นี่เป็นวิธีที่ง่ายในการค้นหาดัชนี N ค่าน้อยที่สุด / ใหญ่ที่สุดในเวกเตอร์ (ตัวอย่างสำหรับ N = 3):
N <- 3
N ที่เล็กที่สุด:
ndx <- order(x)[1:N]
N ที่ใหญ่ที่สุด:
ndx <- order(x, decreasing = T)[1:N]
ดังนั้นคุณสามารถแยกค่าเป็น:
x[ndx]
สำหรับค่าสูงสุดที่ n
sort(x, TRUE)[n]
ฉันพบว่าการลบองค์ประกอบสูงสุดก่อนแล้วจึงดำเนินการอีกค่าสูงสุดด้วยความเร็วที่เทียบเคียงได้:
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
นี่คือวิธีที่ง่ายที่สุดที่ฉันพบ
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
เมื่อเร็ว ๆ นี้ฉันกำลังมองหาฟังก์ชันR ที่ส่งคืนดัชนีของจำนวนสูงสุด / นาที N สูงสุดในเวกเตอร์ที่กำหนดฉันประหลาดใจที่ไม่มีฟังก์ชั่นดังกล่าว
และนี่คือสิ่งที่คล้ายกันมาก
วิธีการแก้ปัญหากำลังดุร้ายโดยใช้ฟังก์ชัน:: baseดูเหมือนจะเป็นวิธีที่ง่ายที่สุด
topMaxUsingFullSort <- function(x, N) {
sort(x, decreasing = TRUE)[1:min(N, length(x))]
}
แต่มันไม่ได้เป็นหนึ่งที่เร็วที่สุดในกรณีของคุณไม่มีค่าค่อนข้างเล็กเมื่อเทียบกับความยาวของเวกเตอร์x
ในอีกด้านหนึ่งถ้าNมีขนาดเล็กมากคุณสามารถใช้base :: ซึ่งฟังก์ชั่นmaximer iteratively และในแต่ละการทำซ้ำคุณสามารถแทนที่ค่าที่พบโดย-Inf
# 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
}
ฉันเชื่อว่าคุณเห็นปัญหา - ลักษณะการคัดลอกเมื่อแก้ไขของ R ดังนั้นสิ่งนี้จะทำงานได้ดีขึ้นสำหรับ N ขนาดเล็กมาก (1,2,3) แต่มันจะช้าลงอย่างรวดเร็วสำหรับค่า N ที่มากขึ้น และคุณจะทำซ้ำมากกว่าองค์ประกอบทั้งหมดในเวกเตอร์x Nครั้ง
ผมคิดว่าทางออกที่ดีที่สุดในการทำความสะอาดRคือการใช้บางส่วนฐาน :: การจัดเรียง
topMaxUsingPartialSort <- function(x, N) {
N <- min(N, length(x))
x[x >= -sort(-x, partial=N)[N]][1:N]
}
จากนั้นคุณสามารถเลือกรายการสุดท้าย ( N th) จากผลลัพธ์ของฟังก์ชั่น defiend ด้านบน
หมายเหตุ: ฟังก์ชั่นที่กำหนดไว้ด้านบนเป็นเพียงตัวอย่าง - หากคุณต้องการใช้พวกเขาคุณต้องตรวจสอบ / อินพุตที่มีสติ (เช่นN> length (x) )
ฉันเขียนบทความเล็ก ๆ เกี่ยวกับสิ่งที่คล้ายกันมาก (รับดัชนีของค่าสูงสุด N / min สูงสุดของเวกเตอร์) ที่http://palusga.cz/?p=18 - คุณสามารถหาเกณฑ์มาตรฐานของฟังก์ชั่นที่คล้ายกันที่ฉันกำหนดไว้ด้านบน
head(sort(x),..)
หรือtail(sort(x),...)
ควรทำงาน
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)
}
ฟังก์ชั่นนี้จะส่งกลับเมทริกซ์ที่มีค่าสูงสุด n และดัชนีของพวกเขา หวังว่ามันจะช่วย VDevi-Chou
นี่จะหาดัชนีของค่าที่น้อยที่สุดหรือมากที่สุดของ N ในเวกเตอร์ตัวเลขอินพุต x กำหนด bottom = TRUE ในอาร์กิวเมนต์หากคุณต้องการ N'th จากด้านล่างหรือล่าง = FALSE หากคุณต้องการ N'th จากด้านบน N = 1 และ bottom = TRUE เทียบเท่ากับ which.min, N = 1 และ bottom = FALSE เทียบเท่ากับ which.max
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)
}
dplyr มีฟังก์ชัน nth โดยที่อาร์กิวเมนต์แรกคือเวกเตอร์และอันที่สองคือตำแหน่งที่คุณต้องการ สิ่งนี้จะไปสำหรับองค์ประกอบที่ทำซ้ำเช่นกัน ตัวอย่างเช่น:
x = c(1,2, 8, 16, 17, 20, 1, 20)
การหาค่าที่ใหญ่เป็นอันดับสอง:
nth(unique(x),length(unique(x))-1)
[1] 17
x[[order(order_by)[[n]]]]
- ดังนั้นจึงจำเป็นต้องมีการเรียงลำดับเวกเตอร์ทั้งหมด ดังนั้นจะไม่เร็วเท่ากับคำตอบที่ยอมรับ
sort
กับบางส่วน = อาร์กิวเมนต์ (ซึ่งทุกอย่างเปลี่ยนแปลง)
dplyr::nth()
หรือไม่? bench::mark(max(x[-which.max(x)]), x[[order(-x)[[2]]]] )
, nth()
ดูเหมือนว่าเกือบ 10 ครั้งช้าซึ่งlength(x)
เป็น 3 ล้าน
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
คุณสามารถใช้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 หมายเลขแรก
topn
ฟังก์ชั่นซึ่งจะเร็วกว่าsort
, และorder
nth
ดูเอกสารประกอบ