按组和列之间查找最小值
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"))
【讨论】:
以上是关于按组和列之间查找最小值的主要内容,如果未能解决你的问题,请参考以下文章