如何根据另一个向量的值对一个向量进行排序


112

我有一个向量x,我想根据向量y中值的顺序进行排序。两个向量的长度不同。

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

预期结果将是:

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

Answers:


70

这是一个班轮...

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

[编辑:]分解如下:

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
这非常简洁,但是我很难弄清楚那里发生了什么。您能详细说明一下吗?
马特·帕克

3
这很漂亮,并且很好地理解了R的内置函数。+1
Godeke

6
通常,即使y不是1:length(y)的置换,也可能要这样做。在这种情况下,此解决方案不起作用,但下面的gd047解决方案x [order(match(x,y))]可以解决。
Rahul Savani

5
我实际上对为什么要进行40次投票感到困惑。在x和上进行了许多简单的变体后,它失败了yx <- c(1,4,2); y <- c(1,2,4)例如。
thelatemail 2015年

1
@thelatemail,我同意。停止疯狂并否决这个答案!
伊恩·研究员2015年

184

这个如何

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

29
这是非常好的,比接受的答案恕我直言更好,因为它更通用。
fmark

2
我会说这应该在基本的GNU-R中。
灾难性故障,

当同时使用x和y的字符向量时,此答案对我来说效果很好。在接受的答案中添加分解/轻微阐述会很好
小牛

4

您可以将其转换x为有序因子:

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

显然,将数字转换为因子可以从根本上改变下游代码对的反应方式x。但是,由于您没有给我们提供有关接下来发生的情况的任何信息,我认为我建议将此作为一种选择。


1
这应该是最好的答案,因为它适用于非整数情况;或x在排序向量中的值不在排序向量y中但略有变化时也可以工作: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

怎么样?:

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

(伊恩的可能还更好)


2

如果您需要获得“ y”的订单,无论是数字还是字符:

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

步骤:

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

[ 编辑:显然,伊恩(Ian)有正确的做法,但我将其保留供后人参考。]

您可以通过在y向量上建立索引来实现无循环操作。将递增的数值添加到y并将它们合并:

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

z中的结果:4 4 4 2 2 1 3 3 3

重要步骤:

  1. for(i in y)-循环关注元素

  2. z <-c(z,...)-依次连接每个子表达式

  3. rep(i,sum(x == i))-重复i(当前感兴趣的元素)sum(x == i)次(在x中找到i的次数)。


0

您还可以sqldf通过以下join功能使用和执行此功能sql

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]]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.