[英]How to sort a dataframe in R by one variable while grouping for others
我有一個數據框:
library(tidyverse)
test_frame <- tibble(var_1 = rep(c("a", "b"), 5),
var_2 = c("a1", "a1", "a2", "a2", "a3", "a3", "a4", "a4", "a5", "a5"),
var_3 = runif(10, min = 1, max = 5))
test_frame
# A tibble: 10 x 3
var_1 var_2 var_3
<chr> <chr> <dbl>
1 a a1 4.00
2 b a1 4.12
3 a a2 2.77
4 b a2 1.33
5 a a3 3.95
6 b a3 3.02
7 a a4 2.44
8 b a4 2.57
9 a a5 1.35
10 b a5 2.11
我希望它按 var_3 排序,但僅用於 var_1 中值為“a”的行,以將 var_2 中具有相同值的行保持在一起。 像那樣:
# A tibble: 10 x 3
var_1 var_2 var_3
<chr> <chr> <dbl>
1 a a1 4.00
2 b a1 4.12
5 a a3 3.95
6 b a3 3.02
3 a a2 2.77
4 b a2 1.33
7 a a4 2.44
8 b a4 2.57
9 a a5 1.35
10 b a5 2.11
我嘗試了不同的“group_by”和“arrange”組合但沒有成功。 我錯過了什么?
使用基數 R,按由“var_2”加倍的“var_3”值排序。
with(test_frame, test_frame[order(-rep(var_3[!duplicated(var_2)], each=2)), ])
# # A tibble: 10 x 3
# var_1 var_2 var_3
# <chr> <chr> <dbl>
# 1 a a4 4.79
# 2 b a4 1.33
# 3 a a2 3.24
# 4 b a2 4.62
# 5 a a5 3.06
# 6 b a5 2.56
# 7 a a3 1.55
# 8 b a3 4.96
# 9 a a1 1.47
# 10 b a1 2.90
數據
test_frame <- structure(list(var_1 = c("a", "b", "a", "b", "a", "b", "a", "b",
"a", "b"), var_2 = c("a1", "a1", "a2", "a2", "a3", "a3", "a4",
"a4", "a5", "a5"), var_3 = c(1.46994944661856, 2.89998832624406,
3.24133098497987, 4.61612554918975, 1.55484067089856, 4.95556691568345,
4.78667293023318, 1.32975023239851, 3.05684713739902, 2.56081386841834
)), row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"
))
一種dplyr
選項可能是:
test_frame %>%
mutate(ranking = dense_rank(desc((var_1 == "a") * var_3))) %>%
group_by(var_2) %>%
mutate(ranking = min(ranking)) %>%
arrange(ranking) %>%
select(-ranking)
var_1 var_2 var_3
<chr> <chr> <dbl>
1 a a4 4.46
2 b a4 2.68
3 a a5 2.80
4 b a5 2.65
5 a a1 1.91
6 b a1 2.99
7 a a3 1.22
8 b a3 1.93
9 a a2 1.10
10 b a2 4.92
或者:
test_frame %>%
filter(var_1 == "a") %>%
mutate(ranking = dense_rank(desc(var_3))) %>%
bind_rows(test_frame %>%
filter(var_1 == "b")) %>%
group_by(var_2) %>%
mutate(ranking = min(ranking, na.rm = TRUE)) %>%
arrange(ranking) %>%
select(-ranking)
一種解決方案是pivot_wider
以便您對完整變量進行排序,然后排序,然后pivot_longer
返回原始形狀。
test_frame %>%
pivot_wider( names_from = var_1, values_from = var_3) %>%
arrange( -a) %>%
pivot_longer(cols=c(a,b), names_to="var_1", values_to = "var_3")
# A tibble: 10 x 3
var_2 var_1 var_3
<chr> <chr> <dbl>
1 a1 a 4.21
2 a1 b 1.82
3 a5 a 3.71
4 a5 b 1.25
5 a3 a 2.76
6 a3 b 2.58
7 a2 a 2.60
8 a2 b 4.32
9 a4 a 1.12
10 a4 b 1.54
無需對數據dplyr::arrange()
列進行分組、添加和刪除 - 這只是很好地使用了dplyr::arrange()
方法。 我認為這可以為您提供所需的東西:
as.data.frame(test_frame) %>% arrange(var_3, var_1, var_2)
這給你這個:
var_1 var_2 var_3
1 b a4 1.866265
2 a a4 2.703378
3 b a5 2.931703
4 a a1 2.935217
5 a a2 3.019241
6 b a1 3.029589
7 b a3 3.657182
8 a a3 4.392643
9 b a2 4.415388
10 a a5 4.498499
唯一的問題是 var_2 排序為 'b',然后是 'a' - 而不是 'a',然后是 'b',就像你想要的那樣。 可能有幾種方法(您可以在arrange()
函數中使用desc(...)
...但我在讓它工作時遇到了一些麻煩。最后,您實際上可以分離出arrange()
功能,哪種行為以特定順序對每一列進行排序。這是我為您提供的最終解決方案:
as.data.frame(test_frame) %>% arrange(var_3) %>% arrange(var_1) %>% arrange(var_2)
var_1 var_2 var_3
1 a a1 2.935217
2 b a1 3.029589
3 a a2 3.019241
4 b a2 4.415388
5 a a3 4.392643
6 b a3 3.657182
7 a a4 2.703378
8 b a4 1.866265
9 a a5 4.498499
10 b a5 2.931703
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.