根据具有特定顺序的向量对数据帧行进行排序

Rap*_*ter 141 sorting r dataframe

有没有更简单的方法来确保数据框的行按照我在下面的简短示例中实现的"目标"向量进行排序?

df <- data.frame(name = letters[1:4], value = c(rep(TRUE, 2), rep(FALSE, 2)))

df
#   name value
# 1    a  TRUE
# 2    b  TRUE
# 3    c FALSE
# 4    d FALSE

target <- c("b", "c", "a", "d")
Run Code Online (Sandbox Code Playgroud)

为了完成工作,这似乎有点太"复杂"了:

idx <- sapply(target, function(x) {
    which(df$name == x)
})
df <- df[idx,]
rownames(df) <- NULL

df 
#   name value
# 1    b  TRUE
# 2    c FALSE
# 3    a  TRUE
# 4    d FALSE
Run Code Online (Sandbox Code Playgroud)

Edw*_*ard 209

试试match:

df <- data.frame(name=letters[1:4], value=c(rep(TRUE, 2), rep(FALSE, 2)))
target <- c("b", "c", "a", "d")
df[match(target, df$name),]

  name value
2    b  TRUE
3    c FALSE
1    a  TRUE
4    d FALSE
Run Code Online (Sandbox Code Playgroud)

只要您target包含完全相同的元素df$name,它就会起作用,并且都不包含重复值.

来自?match:

match returns a vector of the positions of (first) matches of its first argument 
in its second.
Run Code Online (Sandbox Code Playgroud)

因此match找到与target元素匹配的行号,然后df按顺序返回.

  • 不确定这是最干净的方式,但只有“基本”功能,如果您在 df 中有重复项,这应该可以工作:`df &lt;- data.frame(name=letters[c(1:4, 1:4)], value=c(rep(TRUE, 2), rep(FALSE, 2),rep(TRUE, 2), rep(FALSE, 2))) 目标 &lt;- c("b", "c", "a", "d") df[order(unlist(sapply(df$name, function(x) which(target == x)))),] ` (2认同)

小智 20

我更喜欢***_joindplyr需要匹配数据时使用.一个可能的尝试

left_join(data.frame(name=target),df,by="name")
Run Code Online (Sandbox Code Playgroud)

请注意,***_joinrequire tbls或data.frame 的输入

  • 并使用管道语法:`df%&gt;%right_join(tibble(name = target),by =“ name”)` (2认同)
  • 请小心。自 dplyr 1.0.0 以来,这不再可能。一个突破性的改变。请参阅[变更日志](https://dplyr.tidyverse.org/news/index.html#writing-changes) (2认同)

Ron*_*hah 20

我们可以根据以下因素调整因子水平target并将其用于arrange

library(dplyr)
df %>% arrange(factor(name, levels = target))

#  name value
#1    b  TRUE
#2    c FALSE
#3    a  TRUE
#4    d FALSE
Run Code Online (Sandbox Code Playgroud)

或者order它并使用它slice

df %>% slice(order(factor(name, levels = target)))
Run Code Online (Sandbox Code Playgroud)

  • 我认为最好的解决方案 (4认同)
  • 仅当“目标”向量包含与“名称”向量相同的元素时才适用;否则,秩序就会被打破。 (2认同)

Mat*_*ttV 18

这种方法有点不同,它为我提供了比前一个答案更多的灵活性.通过使其成为有序因子,您可以很好地使用它arrange等等.我在gdata包中使用了reorder.factor .

df <- data.frame(name=letters[1:4], value=c(rep(TRUE, 2), rep(FALSE, 2)))
target <- c("b", "c", "a", "d")

require(gdata)
df$name <- reorder.factor(df$name, new.order=target)
Run Code Online (Sandbox Code Playgroud)

接下来,使用它现在订购的事实:

require(dplyr)
df %>%
  arrange(name)
    name value
1    b  TRUE
2    c FALSE
3    a  TRUE
4    d FALSE
Run Code Online (Sandbox Code Playgroud)

如果要返回原始(字母)顺序,只需使用as.character()它将其恢复到原始状态.

  • @Reilstein `setDT(df)[, name := factor(name, levels = target)]`。然后看到两个`data.table`答案[这里](http://stackoverflow.com/questions/1296646/how-to-sort-a-dataframe-by-columns/) (4认同)
  • 有人知道这个的 data.table 版本吗? (2认同)