将数据帧行按向量按特定顺序排序

是否有一种更简单的方法来确保数据帧的行按照“目标”向量进行排序,就像我在下面的简短示例中实现的那样?

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

这似乎有点太“复杂”了,无法完成工作:

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
176109 次浏览

试试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

只要你的target包含与df$name完全相同的元素,并且都不包含重复的值,它就可以工作。

?match:

match returns a vector of the positions of (first) matches of its first argument
in its second.

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

这个方法有点不同,它比之前的答案提供了更多的灵活性。 通过将其转换为有序因子,可以在arrange等中很好地使用它。我用的是重新排序。

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

接下来,利用它现在是有序的事实:

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

如果你想回到最初的(字母)排序,只需使用as.character()让它回到最初的状态。

当我需要匹配数据时,我更喜欢在dplyr中使用***_join。一个可能的尝试

left_join(data.frame(name=target),df,by="name")

注意,***_join的输入需要tbls或data.frame

我们可以根据target调整因子级别,并在arrange中使用它

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


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

或者order它并在slice中使用它

df %>% slice(order(factor(name, levels = target)))

如果你不想使用任何库,并且你的数据中有重复出现的情况,你也可以使用whichsapply

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

这是一个类似的系统,在这种情况下,你有一个变量,你想要排序,但然后你想要排序一个辅助变量根据这个辅助变量在初始排序中第一次出现的顺序。

在下面的函数中,初始排序变量被称为order_by,次要变量被称为order_along——就像“按照这个变量的初始顺序”一样。

library(dplyr, warn.conflicts = FALSE)
df <- structure(
list(
msoa11hclnm = c(
"Bewbush", "Tilgate", "Felpham",
"Selsey", "Brunswick", "Ratton", "Ore", "Polegate", "Mile Oak",
"Upperton", "Arundel", "Kemptown"
),
lad20nm = c(
"Crawley", "Crawley",
"Arun", "Chichester", "Brighton and Hove", "Eastbourne", "Hastings",
"Wealden", "Brighton and Hove", "Eastbourne", "Arun", "Brighton and Hove"
),
shape_area = c(
1328821, 3089180, 3540014, 9738033, 448888, 10152663, 5517102,
7036428, 5656430, 2653589, 72832514, 826151
)
),
row.names = c(NA, -12L), class = "data.frame"
)

这并没有给我我所需要的:

df %>%
dplyr::arrange(shape_area, lad20nm)
#>    msoa11hclnm           lad20nm shape_area
#> 1    Brunswick Brighton and Hove     448888
#> 2     Kemptown Brighton and Hove     826151
#> 3      Bewbush           Crawley    1328821
#> 4     Upperton        Eastbourne    2653589
#> 5      Tilgate           Crawley    3089180
#> 6      Felpham              Arun    3540014
#> 7          Ore          Hastings    5517102
#> 8     Mile Oak Brighton and Hove    5656430
#> 9     Polegate           Wealden    7036428
#> 10      Selsey        Chichester    9738033
#> 11      Ratton        Eastbourne   10152663
#> 12     Arundel              Arun   72832514

这是一个函数:

order_along <- function(df, order_along, order_by) {
cols <- colnames(df)
  

df <- df %>%
dplyr::arrange(\{\{ order_by }})
  

df %>%
dplyr::select(\{\{ order_along }}) %>%
dplyr::distinct() %>%
dplyr::full_join(df) %>%
dplyr::select(dplyr::all_of(cols))
  

}


order_along(df, lad20nm, shape_area)
#> Joining, by = "lad20nm"
#>    msoa11hclnm           lad20nm shape_area
#> 1    Brunswick Brighton and Hove     448888
#> 2     Kemptown Brighton and Hove     826151
#> 3     Mile Oak Brighton and Hove    5656430
#> 4      Bewbush           Crawley    1328821
#> 5      Tilgate           Crawley    3089180
#> 6     Upperton        Eastbourne    2653589
#> 7       Ratton        Eastbourne   10152663
#> 8      Felpham              Arun    3540014
#> 9      Arundel              Arun   72832514
#> 10         Ore          Hastings    5517102
#> 11    Polegate           Wealden    7036428
#> 12      Selsey        Chichester    9738033

reprex包 (v0.3.0)创建于2021-01-12