Làm cách nào để sắp xếp một vectơ dựa trên các giá trị của một vectơ khác


112

Tôi có một vectơ x, mà tôi muốn sắp xếp dựa trên thứ tự của các giá trị trong vectơ y. Hai vectơ không cùng độ dài.

x <- c(2, 2, 3, 4, 1, 4, 4, 3, 3)
y <- c(4, 2, 1, 3)

Kết quả mong đợi sẽ là:

[1] 4 4 4 2 2 1 3 3 3

Câu trả lời:


70

Đây là một lớp lót ...

y[sort(order(y)[x])]

[sửa:] Điều này được chia nhỏ như sau:

order(y)             #We want to sort by y, so order() gives us the sorting order
order(y)[x]          #looks up the sorting order for each x
sort(order(y)[x])    #sorts by that order
y[sort(order(y)[x])] #converts orders back to numbers from orders

1
Điều đó rất ngắn gọn, nhưng tôi đang gặp khó khăn trong việc hình dung chuyện gì đang xảy ra ở đó. Bạn có thể giải thích một chút?
Matt Parker

3
Điều này khá hay và cho thấy sự hiểu biết tốt về các tính năng tích hợp của R. +1
Godeke

6
Nói chung, người ta có thể muốn làm điều này ngay cả khi y không phải là hoán vị của 1: length (y). Trong trường hợp đó, giải pháp này không hoạt động, nhưng giải pháp của gd047 dưới đây, x [order (match (x, y))], thì có.
Rahul Savani

5
Tôi thực sự bối rối không hiểu tại sao điều này lại có 40 phiếu ủng hộ. Nó không thành công cho rất nhiều biến thể đơn giản trên xy. x <- c(1,4,2); y <- c(1,2,4)ví dụ.
thelatemail

1
@thelatemail Tôi đồng ý. Hãy dừng sự điên rồ và phản đối câu trả lời này!
Ian Fellows

184

cái này thì sao

x[order(match(x,y))]

29
Đây là câu trả lời rất hay, tốt hơn câu trả lời được IMHO chấp nhận vì nó chung chung hơn.
fmark

2
Tôi muốn nói rằng điều này phải có trong GNU-R cơ sở.
thảm họa-thất bại

Câu trả lời này hoạt động tốt đối với tôi khi sử dụng vectơ ký tự cho cả x và y. Thêm một phân tích / chỉnh sửa nhẹ như trong câu trả lời được chấp nhận sẽ rất hay
mavericks

4

Bạn có thể chuyển đổi xthành một yếu tố có thứ tự:

x.factor <- factor(x, levels = y, ordered=TRUE)
sort(x)
sort(x.factor)

Rõ ràng, việc thay đổi các số của bạn thành các yếu tố có thể thay đổi hoàn toàn cách phản ứng của mã ở phía dưới x. Nhưng vì bạn không cung cấp cho chúng tôi bất kỳ bối cảnh nào về những gì xảy ra tiếp theo, tôi nghĩ tôi sẽ đề xuất điều này như một lựa chọn.


1
đây phải là câu trả lời tốt nhất vì nó sẽ hoạt động cho các trường hợp không phải là số nguyên; hoặc cũng làm việc khi có giá trị trong xkhông nằm trong vector sắp xếp yvới thay đổi nhỏ:x <- c(2, 2, 3, 4, 1, 4, 4, 3, 3, 6); y <- c(4, 2, 1, 3); as.numeric(as.character(sort(factor(x, unique(c(y, x))))))
RAWR

2

Làm thế nào về?:

rep(y,table(x)[as.character(y)])

(Ian có lẽ vẫn tốt hơn)


2

Trong trường hợp bạn cần đặt hàng trên "y" cho dù đó là số hay ký tự:

x[order(ordered(x, levels = y))]
4 4 4 2 2 1 3 3 3

Theo các bước:

a <- ordered(x, levels = y) # Create ordered factor from "x" upon order in "y".
[1] 2 2 3 4 1 4 4 3 3
Levels: 4 < 2 < 1 < 3

b <- order(a) # Define "x" order that match to order in "y".
[1] 4 6 7 1 2 5 3 8 9

x[b] # Reorder "x" according to order in "y".
[1] 4 4 4 2 2 1 3 3 3

1

[ Chỉnh sửa: Rõ ràng Ian có cách tiếp cận đúng, nhưng tôi sẽ để lại điều này cho hậu thế.]

Bạn có thể làm điều này mà không cần vòng lặp bằng cách lập chỉ mục trên vectơ y của bạn. Thêm một giá trị số tăng dần vào y và hợp nhất chúng:

y <- data.frame(index=1:length(y), x=y)
x <- data.frame(x=x)
x <- merge(x,y)
x <- x[order(x$index),"x"]
x
[1] 4 4 4 2 2 1 3 3 3

0
x <- c(2, 2, 3, 4, 1, 4, 4, 3, 3)
y <- c(4, 2, 1, 3)
for(i in y) { z <- c(z, rep(i, sum(x==i))) }

Kết quả trong z: 4 4 4 2 2 1 3 3 3

Các bước quan trọng:

  1. for (i in y) - Vòng lặp qua các phần tử quan tâm.

  2. z <- c (z, ...) - Lần lượt nối từng biểu thức con

  3. rep (i, sum (x == i)) - Lặp lại i (phần tử hiện tại được quan tâm) sum (x == i) lần (số lần chúng tôi tìm thấy i trong x).


0

Ngoài ra, bạn có thể sử dụng sqldfvà làm điều đó bằng một joinchức năng sqlnhư sau:

library(sqldf)
x <- data.frame(x = c(2, 2, 3, 4, 1, 4, 4, 3, 3))
y <- data.frame(y = c(4, 2, 1, 3))

result <- sqldf("SELECT x.x FROM y JOIN x on y.y = x.x")
ordered_x <- result[[1]]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.