组合分析以最大化 R 中的值

Combinatorial analysis to maximize a value in R

我有以下 table:

df = structure(list(test_id = c(1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4), person = structure(c(1L, 
2L, 3L, 2L, 3L, 1L, 2L, 3L, 4L, 1L, 3L), .Label = c("a", "b", 
"c", "d"), class = "factor"), points = c(1, 5, 2, 6, 5, 3, 4, 
5, 6, 2, 1)), .Names = c("test_id", "person", "points"), row.names = c(NA, 
-11L), class = "data.frame")

我想确定几个场景,在场景 2 和场景 3 上需要您的帮助:

  1. 哪一个人在所有测试中得分最高, 例如使用 dplyr: df %>% group_by(person) %>% summarize(most_points = sum(points)) %>% top_n(1,most_points)
  2. 哪两个人在所有测试中得分最高(每次测试取两人之间的最大分值)

    预期输出:a人和b人将是最好的两人组合,他们的分数总和为17(b赢得测试1,2&3和a赢得测试 4)。

  3. 哪三个人在所有测试中得分最高(每次测试取三个人之间的最大分值)

    预期输出:a、b、c 将是最佳三人组合,他们的分数总和为 19(b 赢得测试 1 和 2 , d 赢得测试 3, a 赢得测试 4)

这是一个非常简化的 table,实际上我有数十万行我将与更多的人和 test_id 一起分析。请注意,并非每个人的每次测试都有分值。我对加权平均值不感兴趣,只是 他们(或 two/three 的组合)累积的最大分数

前两位

df %>% 
  group_by(person) %>% 
  summarize(most_points = sum(points)) %>% 
  arrange(desc(most_points)) %>%
  top_n(2, most_points)

# A tibble: 2 × 2
  person most_points
  <fctr>       <dbl>
1      b          20
2      c           8

前三名(真四人并列)

df %>% 
  group_by(person) %>% 
  summarize(most_points = sum(points)) %>% 
  arrange(desc(most_points)) %>%
  top_n(3, most_points)

# A tibble: 4 × 2
  person most_points
  <fctr>       <dbl>
1      b          20
2      c           8
3      a           6
4      d           6

来到这里花了一些时间,但这是您可以做的。 我们将首先更改数据的格式:

library(tidyr)
dfs=spread(df,person,points)
dfs[is.na(dfs)]=0
pers=unique(df$person)

这个returns:

  test_id a b c d
1       1 1 5 2 0
2       2 0 6 5 0
3       3 3 4 5 6
4       4 2 0 1 0

然后,我们将寻找两个人使用 combn 的所有组合,并为每个测试确定两者之间的最大值,并将其在所有测试中求和。这样我们就可以确定总和最高的对:

cc2=combn(1:length(pers),2)
values2 = sapply(1:ncol(cc2),function(i) sum(apply(dfs[,cc2[,i]+1],1,function(x) max(x))))
names(values2) = apply(cc2,2,function(x) paste(pers[x],collapse="-"))
values2=values2[values2==max(values2)]

这个returns:

a-b b-c b-d 
 17  17  17 

对于3人的组合,我们做同样的事情:

cc3=combn(1:length(pers),3)
values3 = sapply(1:ncol(cc3),function(i) sum(apply(dfs[,cc3[,i]+1],1,function(x) max(x))))
names(values3) = apply(cc3,2,function(x) paste(pers[x],collapse="-"))
values3=values3[values3==max(values3)]

这个returns:

a-b-d 
   19