【问题标题】:Extract row corresponding to maximum value by group for multiple variables为多个变量按组提取最大值对应的行
【发布时间】:2021-11-11 03:52:12
【问题描述】:

我有一个按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

这是我想要/预期的输出:

    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

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

任何帮助将不胜感激!

【问题讨论】:

  • 我很好奇“提取代表每个变量最大值的行”。根据您提供的链接,您的结果是否需要是矩阵列表?
  • 您的预期输出是什么?你需要dt[, lapply(.SD, max), .SDcols = variables, by = "ID"] 吗?
  • 有关 tidyverse 解决方案,请查看 slice_max()。由于您可能会为每个变量的最大值选择不同的行,因此您需要指定所需输出的格式。有很多可能性...
  • 更简单:dt1[, lapply(.SD, which.max), by = "ID"]。不需要参数.SDcols。而且我没有看到输出有任何问题。
  • @RonakShah 和 Limey:我已经用我想要的输出编辑了这个问题。此外,Ronak 的解决方案有效。为什么max 可以工作,而which.max 不行?

标签: r data.table lapply


【解决方案1】:

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

x <- 4:1

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

这里which.max 返回 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

【讨论】:

    猜你喜欢
    • 2014-07-27
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    相关资源
    最近更新 更多