是否有更简单的方法来确保数据框的行按照我在下面的简短示例中实现的“目标”向量进行排序?
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
答案 0 :(得分:191)
尝试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
。
答案 1 :(得分: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)
接下来,请使用现在订购的事实:
require(dplyr)
df %>%
arrange(name)
name value
1 b TRUE
2 c FALSE
3 a TRUE
4 d FALSE
如果您想返回原始(字母)排序,只需使用as.character()
将其恢复为原始状态。
答案 2 :(得分:16)
每当我需要匹配数据时,我更愿意在***_join
中使用dplyr
。一个可能尝试这个
left_join(data.frame(name=target),df,by="name")
请注意,***_join
的输入需要tbls或data.frame
答案 3 :(得分:6)
我们可以根据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)))
答案 4 :(得分:2)
如果您不想使用任何库并且数据中有重复出现,则也可以将WM_CHAR
与which
一起使用。
sapply
答案 5 :(得分:1)
这里有一个类似的系统,适用于以下情况:您有一个最初想要排序的变量,但随后您想根据该次要变量在初始排序中首次出现的顺序对次要变量进行排序。
>在下面的函数中,初始排序变量称为 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 package (v0.3.0) 于 2021 年 1 月 12 日创建