R 使用每个组的最大值按组排序
是否有一种方法可以通过减小每个组的最大值按组排序,并通过减小值在组内排序 输入R 使用每个组的最大值按组排序,r,R,是否有一种方法可以通过减小每个组的最大值按组排序,并通过减小值在组内排序 输入 按名称分组,创建一个临时列,然后按名称和值排列 df %>% group_by(Name) %>% mutate(mx = max(Value)) %>% arrange(desc(mx), desc(Value)) %>% select(-mx) 这是一个dplyr解决方案。有关基准测试,请参见@UweBlock的答案 library(dplyr) x %>% gr
按名称分组,创建一个临时列,然后按名称和值排列
df %>% group_by(Name) %>%
mutate(mx = max(Value)) %>%
arrange(desc(mx), desc(Value)) %>%
select(-mx)
这是一个dplyr解决方案。有关基准测试,请参见@UweBlock的答案
library(dplyr)
x %>% group_by(Name) %>% # group by Name
mutate(NameMax = max(Value)) %>% # create a temp variable holding the max of each Name
arrange(desc(NameMax), desc(Value)) %>% # arrange with two columns
select(Name, Value) # select only the two input columns
# Name Value
# <fctr> <int>
# 1 B 90
# 2 B 80
# 3 B 70
# 4 A 40
# 5 A 35
# 6 A 20
# 7 C 30
# 8 C 20
# 9 C 10
编辑:更正和基准
在准备基准测试的过程中,我注意到我的一些解决方案只处理OP提供的偏序样本数据,但在处理任意乱序数据时失败。我已经从我的答案中删除了这些,但它们仍然可以从历史中找到
添加的基准测试部分比较了基本R、data.table和两种dpylr解决方案在两种不同问题大小上的差异
为完整起见,以下是两个data.table和一个base R解决方案:
1.数据表
@Frank提出了一个更简洁的data.table解决方案:
X <- data.table(x)
X[order(-Value), .SD, by = Name]
基准
为了针对不同的问题规模运行基准测试,我们需要构建样本数据:
library(magrittr)
library(data.table)
# prepare data
n_rows <- 1E1
set.seed(1234L)
x0 <- data.frame(
Name = sample(LETTERS[seq_len(min(round(n_rows/3), length(LETTERS)))], n_rows, TRUE),
Value = sample(n_rows))
# coerce to data.table
X0 <- data.table(x0)
baser显然是最快的,其次是data.table方法,最后是dplyr方法。dplyr之间的差异很有趣。似乎dplyr::select mx比dplyr::selectName更快,也就是说,它的开销更小,而dplyr::selectName是代码中唯一的区别
对于100万行n_行,我想在某些地方可能有重复,但基本R习惯用法是x[withx,order aveValue,Name,FUN=max],希望您会发现值得注意的是我添加了一个。希望您会发现值得注意的是我添加了一个。@Frank Benchmark显示了您的数据。表方法最快。很好的总结。我引用了你的答案。
library(data.table)
X <- data.table(x)
X[, tmp := max(Value), by = Name][order(-tmp, -Value)][, tmp := NULL][]
Name Value
1: B 90
2: B 80
3: B 70
4: A 40
5: A 35
6: A 20
7: C 30
8: C 20
9: C 10
X <- data.table(x)
X[order(-Value), .SD, by = Name]
x[with(x, order(-ave(Value, Name, FUN = max), -Value)), ]
Name Value
6 B 90
5 B 80
4 B 70
2 A 40
3 A 35
1 A 20
9 C 30
8 C 20
7 C 10
library(magrittr)
library(data.table)
# prepare data
n_rows <- 1E1
set.seed(1234L)
x0 <- data.frame(
Name = sample(LETTERS[seq_len(min(round(n_rows/3), length(LETTERS)))], n_rows, TRUE),
Value = sample(n_rows))
# coerce to data.table
X0 <- data.table(x0)
# run benchmarks
microbenchmark::microbenchmark(
copy = x <- copy(x0),
base_avg = {
x <- copy(x0)
x[with(x, order(-ave(Value, Name, FUN = max), -Value)),]
},
dt_tmp = {
X <- copy(X0)
X[, tmp := max(Value), by = Name][order(-tmp, -Value)][, tmp := NULL][]
},
dt_SD = {
X <- copy(X0)
X[order(-Value), .SD, by = Name]
},
dplyr_rt = {
copy(x0) %>%
dplyr::group_by(Name) %>%
dplyr::mutate(mx = max(Value)) %>%
dplyr::arrange(desc(mx), desc(Value)) %>%
dplyr::select(-mx)
},
dplyr_loki = {
copy(x0) %>%
dplyr::group_by(Name) %>% # group by Name
dplyr::mutate(NameMax = max(Value)) %>% # create a temp variable holding the max of each Name
dplyr::arrange(desc(NameMax), desc(Value)) %>% # arrange with two columns
dplyr::select(Name, Value) # select only the two input columns
},
times = 100L
)
Unit: microseconds
expr min lq mean median uq max neval cld
copy 12.839 19.8235 23.69004 24.1660 27.9415 38.892 100 a
base_avg 149.145 193.5115 256.32913 227.8710 243.5400 2180.155 100 a
dt_tmp 951.883 1046.2780 1185.33735 1175.2215 1256.9685 1903.387 100 b
dt_SD 758.184 827.2810 1386.55800 970.0065 1035.5170 40170.486 100 b
dplyr_rt 7329.984 7700.2025 8107.00109 7925.8075 8273.7485 11631.389 100 c
dplyr_loki 8650.386 9059.3065 9820.92511 9269.0525 9745.3710 33805.600 100 d
Unit: milliseconds
expr min lq mean median uq max neval cld
copy 1.378927 1.809747 2.404129 2.268131 2.374798 5.561016 11 a
base_avg 131.783388 143.402694 207.434114 255.460485 259.142658 276.782117 11 c
dt_tmp 70.030740 72.104982 84.694791 75.020852 76.197961 192.827694 11 b
dt_SD 53.406217 55.149698 58.090283 58.156189 60.084684 67.835483 11 b
dplyr_rt 752.707729 779.147098 821.327276 809.360011 878.231387 895.566707 11 d
dplyr_loki 747.559410 765.500369 792.089826 793.458180 803.056861 895.127580 11 d