对多个变量按组提取最大值对应的行

Extract row corresponding to maximum value by group for multiple variables

我有一个按 ID 分组的数据框,每个 ID 有多行,还有几个变量 abc

这是一个玩具示例:

dt <- structure(list(ID = c(1, 1, 2, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 
5, 5, 6, 6, 6, 6, 6, 6, 7, 8, 8, 8, 8, 9, 9, 9, 10, 10), a = c(1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1), b = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1), c = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), d = c(1, 1, 0, 0, 
0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 
0, 0, 0, 0, 1, 1), e = c(0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1), f = c(1, 
1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 
0, 1, 1, 1, 0, 1, 1, 1, 1), g = c(1, 1, 1, 1, 0, 0, 0, 0, 1, 
1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1), h = c(1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1), i = c(1, 1, 1, 1, 
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 
0, 0, 0, 0, 1, 1)), row.names = c(NA, -31L), class = c("tbl_df", 
"tbl", "data.frame"))

对于每个 ID,我想提取代表每个变量最大值的行(取最大值的第一个或最后一个实例不是问题)。当只考虑一个变量 for example 时,有很多例子可以说明如何做到这一点。但是,我很难将其应用于多个变量。

这是我解决问题的尝试(使用 data.tablelapply):

library(data.table)
setDT(dt)
variables = colnames(dt[, 2:10])
dt_max = dt[, lapply(.SD, which.max), .SDcols = variables, by = "ID"]

看看这会产生什么,似乎是对值进行求和,而不是为每个值提取最大值 ID:

    ID a b c d e f g h i
 1:  1 1 1 1 1 2 1 1 1 1
 2:  2 1 1 1 1 1 1 1 1 1
 3:  3 1 1 1 1 5 1 1 2 1
 4:  4 1 1 1 1 1 1 1 1 1
 5:  5 1 1 1 1 1 3 1 1 1
 6:  6 1 1 1 1 1 1 1 1 1
 7:  7 1 1 1 1 1 1 1 1 1
 8:  8 1 1 1 1 1 2 1 2 2
 9:  9 1 1 1 1 1 2 1 1 1
10: 10 1 1 1 1 1 1 1 1 1

这是我的 desired/expected 输出:

    ID a b c d e f g h i
 1:  1 1 1 1 1 1 1 1 1 1
 2:  2 1 1 1 0 0 1 1 0 1
 3:  3 1 1 1 0 1 1 1 1 1
 4:  4 1 1 1 0 0 1 1 0 0
 5:  5 1 1 1 1 1 1 1 0 0
 6:  6 1 1 1 1 1 1 1 0 1
 7:  7 1 1 1 1 1 0 1 0 0
 8:  8 1 1 1 1 0 1 1 1 1
 9:  9 1 1 1 0 1 1 1 0 0
10: 10 1 1 1 1 1 1 1 1 1

我不知道为什么会这样。我唯一的其他想法是分别对每个变量执行此操作,然后将结果合并在一起。但这似乎是一种非常低效的解决问题的方法。

如有任何帮助,我们将不胜感激!

maxwhich.max 是两个不同的函数,做不同的事情。 max 会给出向量中的最大值,而 which.max 会给出向量中最大值的位置。

x <- 4:1

max(x)
#[1] 4
which.max(x)
#[1] 1

此处 which.max returns 1 因为 4 出现在向量 x.

的第一个位置

因此,如果您需要多个列中的 max 个值,您应该使用 max 而不是 which.max

library(data.table)
setDT(dt)
variables = colnames(dt[, 2:10])

dt[, lapply(.SD, max), .SDcols = variables, ID]

#    ID a b c d e f g h i
# 1:  1 1 1 1 1 1 1 1 1 1
# 2:  2 1 1 1 0 0 1 1 0 1
# 3:  3 1 1 1 0 1 1 1 1 1
# 4:  4 1 1 1 0 0 1 1 0 0
# 5:  5 1 1 1 1 1 1 1 0 0
# 6:  6 1 1 1 1 1 1 1 0 1
# 7:  7 1 1 1 1 1 0 1 0 0
# 8:  8 1 1 1 1 0 1 1 1 1
# 9:  9 1 1 1 0 1 1 1 0 0
#10: 10 1 1 1 1 1 1 1 1 1