Bagaimana cara mengurutkan satu vektor berdasarkan nilai-nilai lainnya


112

Saya memiliki vektor x, yang ingin saya sortir berdasarkan urutan nilai dalam vektor y. Kedua vektor tidak memiliki panjang yang sama.

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

Hasil yang diharapkan adalah:

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

Jawaban:


70

Ini satu kapal ...

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

[edit:] Ini memecah sebagai berikut:

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
Itu sangat ringkas, tapi saya kesulitan mencari tahu apa yang terjadi di sana. Bisakah Anda menjelaskan sedikit?
Matt Parker

3
Ini cantik dan menunjukkan pemahaman yang baik tentang built-in R. +1
Godeke

6
Secara umum orang mungkin ingin melakukan ini meskipun y bukan permutasi dari 1: panjang (y). Dalam kasus ini, solusi ini tidak berfungsi, tetapi solusi gd047 di bawah, x [order (match (x, y))], berfungsi.
Rahul Savani

5
Saya sebenarnya bingung mengapa ini memiliki 40 suara positif. Gagal untuk begitu banyak variasi sederhana pada xdan y. x <- c(1,4,2); y <- c(1,2,4)misalnya.
thelatemail

1
@thelatemail Saya setuju. Hentikan kegilaan dan kurangi jawaban ini!
Ian Fellows

184

bagaimana dengan yang satu ini

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

29
Ini sangat bagus, lebih baik daripada jawaban yang diterima IMHO karena lebih umum.
fmark

2
Saya akan mengatakan lebih jauh bahwa ini harus dalam basis GNU-R.
bencana-kegagalan

Jawaban ini bekerja dengan baik untuk saya saat menggunakan vektor karakter untuk x dan y. Menambahkan dekomposisi / sedikit elaborasi seperti pada jawaban yang diterima akan menyenangkan
mavericks

4

Anda dapat mengubahnya xmenjadi faktor yang dipesan:

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

Jelas, mengubah angka Anda menjadi faktor dapat secara radikal mengubah cara kode downstream bereaksi x. Tetapi karena Anda tidak memberi kami konteks apa pun tentang apa yang terjadi selanjutnya, saya pikir saya akan menyarankan ini sebagai opsi.


1
ini harus menjadi jawaban terbaik karena akan bekerja untuk kasus non integer; atau juga bekerja ketika ada nilai di xtidak dalam vektor pengurutan ydengan sedikit perubahan: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

Bagaimana tentang?:

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

(Ian mungkin masih lebih baik)


2

Jika Anda perlu mendapatkan urutan pada "y" tidak peduli apakah itu angka atau karakter:

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

Dengan langkah-langkah:

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

[ Sunting: Jelas Ian memiliki pendekatan yang benar, tapi saya akan membiarkan ini untuk anak cucu.]

Anda dapat melakukan ini tanpa loop dengan mengindeks vektor y Anda. Tambahkan nilai numerik yang bertambah ke y dan gabungkan:

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))) }

Hasil di z: 4 4 4 2 2 1 3 3 3

Langkah-langkah penting:

  1. for (i in y) - Loop di atas elemen yang diminati.

  2. z <- c (z, ...) - Menggabungkan setiap subekspresi secara bergantian

  3. rep (i, sum (x == i)) - Mengulangi i (elemen minat saat ini) jumlah (x == i) kali (berapa kali kami menemukan i dalam x).


0

Anda juga dapat menggunakan sqldfdan melakukannya dengan joinfungsi sqlseperti berikut:

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]]
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.