按组和列之间查找最小值

Posted

技术标签:

【中文标题】按组和列之间查找最小值【英文标题】:Finding minimum by groups and among columns 【发布时间】:2020-09-12 10:36:19 【问题描述】:

我试图在不同的列和组中找到最小值。 我的一小部分数据看起来像这样:

     group cut group_score_1 group_score_2
1        a   1             3           5.0
2        b   2             2           4.0
3        a   0             2           2.5
4        b   3             5           4.0
5        a   2             3           6.0
6        b   1             5           1.0

我想按组分组,对于每个组,在两个组分数中找到包含最小组分数的行,然后还得到包含最小值的列的名称(group_score_1 或 group_score_2), 所以基本上我的结果应该是这样的:

      group cut group_score_1 group_score_2
1        a   0             2           2.5
2        b   1             5           1.0

我尝试了一些想法,最终想出了将其分成几个新的数据框,按组过滤并选择相关列,然后使用which.min(),但我确信有一种更有效的方法它。不知道我错过了什么。

【问题讨论】:

我想遍历行和列并找到具有最小 group_score 的行。然后只保留最低的那一行,告诉我它是哪个组的分数。 下一组得分最低的行,即如果两行的最低组得分相同,则它们之间的切分将是下一组得分最低的行 【参考方案1】:

我们可以使用data.table 方法

library(data.table)
setDT(df)[df[, .I[which.min(do.call(pmin, .SD))], 
     group, .SDcols = patterns('^group_score')]$V1]
#   group cut group_score_1 group_score_2
#1:     a   0             2           2.5
#2:     b   1             5           1.0

【讨论】:

谢谢,@akrun 由于我的数据包含不需要计算的列(逻辑),是否有保留这些列的 data.table 解决方案?【参考方案2】:

对于每个group,您可以计算min 值并选择其中一列中存在该值的行。

library(dplyr)

df %>%
  group_by(group) %>%
  filter(tmp = min(group_score_1, group_score_2);
          group_score_1 == tmp | group_score_2 == tmp)

#  group   cut group_score_1 group_score_2
#  <chr> <int>         <int>         <dbl>
#1 a         0             2           2.5
#2 b         1             5           1  

当您只有两个 group_score 列时,上述方法效果很好。如果您有很多这样的列,则无法用group_score_1 == tmp | group_score_2 == tmp 等列出每一列。在这种情况下,获取长格式数据并获取对应的最小值cut 值并加入数据。假设cut 在每个组中都是唯一的。

df %>%
  tidyr::pivot_longer(cols = starts_with('group_score')) %>%
  group_by(group) %>%
  summarise(cut = cut[which.min(value)]) %>%
  left_join(df, by = c("group", "cut"))

【讨论】:

【参考方案3】:

这是使用pmin + ave + subset 的基本 R 选项

subset(
  df,
  as.logical(ave(
    do.call(pmin, df[grep("group_score_\\d+", names(df))]),
    group,
    FUN = function(x) x == min(x)
  ))
)

给了

  group cut group_score_1 group_score_2
3     a   0             2           2.5
6     b   1             5           1.0

数据

> dput(df)
structure(list(group = c("a", "b", "a", "b", "a", "b"), cut = c(1L, 
2L, 0L, 3L, 2L, 1L), group_score_1 = c(3L, 2L, 2L, 5L, 3L, 5L
), group_score_2 = c(5, 4, 2.5, 4, 6, 1)), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6"))

【讨论】:

以上是关于按组和列之间查找最小值的主要内容,如果未能解决你的问题,请参考以下文章

按组提取对应于变量最小值的行

使用多个连接查找最小值

在 Pandas 数据框中按组过滤具有最小值的行 [重复]

查找两个数组之间的共同最小值

SQL查询以查找列的行值之间的最小差异

数据重复时如何按组查找最小日期