【问题标题】:Iterate over combinations from one row in each index by group in r在 r 中按组从每个索引中的一行迭代组合
【发布时间】:2020-10-03 10:23:26
【问题描述】:

我有一个如下的数据集(示例),

 data <- data.frame(pc = c("A","A","A","A","A","A", "B","B","B","B"),   #categorical 
            index = c(1, 1, 2, 2, 2, 3, 4, 5, 5, 5),                    #categorical 
            g= c(1, 2, 4, 3, 6, 7, 8, 5, 9, 3),                         #numeric 
            h= c(1, 1, 1, 2, 2, 3, 3, 3, 3, 4))                         #categorical 

我想按 'pc' 分组,基于 'index' 遍历所有组合以获得 'g' 中的值的总和以及 'h' 列中的类别数,并保留产生的组合的行'g' 中的最高总和值 + 'h' 中的类别数。

例如在pc=A组中,index=1有两行,index=2有3行,index=3有1行,所以我总共有2x3x1=6个组合(每个组合有3行,一个带index =1,一个索引=2,一个索引=3)。我想保留产生最高的行(每个唯一索引中的一行)(来自'g'的总和值+来自'h'的类别数)。每个pc组的index个数和每个index的长度都不一样。

只是一个可视化 pc=A 组的组合的示例,

 combination sum_of_values_in_g    number_of_categories_in_h
          #1                 12                     2
          #2                 11                     3
          #3                 14                     3
          #4                 13                     2
          #5                 12                     3
          #6                 15                     3

在这个例子中我想要的结果是

 pc index g h
  A     1 2 1
  A     2 6 2
  A     3 7 3
  B     4 8 3
  B     5 9 3

我已经对如何获得组合进行了一些研究 (Iterate over unique combination of groups in a data frameHow to iterate through all combinations of columns and apply function by group in R?Combinations by group in R).. 但我无法弄清楚如何在每个组中获得正确的组合并在每个组合中运行进一步的操作......任何输入或指导将不胜感激!

【问题讨论】:

  • 如果在多个组合中找到最大和最多的类别怎么办?那么,你想得到哪一个,第一个,最后一个,还是全部?此外,如果没有组合同时具有最大的总和和最大的类别数怎么办?那么哪个条件的优先级更高呢?
  • 哦,感谢您的说明。我正在寻找(来自 g 的总和和来自 h 的类别数)的最大总和,所以在示例中,#6 组合给我的值是 18,所以我想保留三行(每行来自 index1、2 , 3) 在最终输出中。如果两种组合产生相同的最终值,则产生的类别数量越多,优先级越高。
  • 什么是number_of_categories_in_h?你是怎么计算的?例如,为什么在您的示例中 #1 是 2
  • #1 组合具有 index=1 的第一行、index=2 的第一行和 index=3 的唯一一行。因此,每一行的类别(来自 h 列)是类别 1、1 和 3,因此 #1 组合共有 2 个类别。

标签: r combinations


【解决方案1】:

这是一个蛮力解决方案。考虑到大型数据集,运行时间可能会非常长。

我们需要这些包中的函数:

library(tidyr)
library(dplyr)
library(purrr)

这是第一步,我们需要一个函数首先将您的数据分成几组 (split(transpose(df), df[[split_by]])),然后在它们之间找到所有可能的 组合 (cross(...)),最后将它们中的每一个合并到一个数据帧中 (lapply(..., bind_rows))。

perm_all <- function(df, split_by){
  lapply(cross(split(transpose(df), df[[split_by]])), bind_rows)
}

transpose 将 n 行数据帧转换为单行数据帧的 n 元素列表)

这是第二步,我们遍历该列表中的所有数据框,看看哪个满足您的要求。

which_max <- function(ls_of_df, numer, categ) {
  test_stats <- vapply(
    ls_of_df, 
    function(df) {
      temp <- length(unique(df[[categ]]))
      c(sum(df[[numer]]) + temp, temp)
    }, 
    double(2L)
  )
  # You could have multiple maxima for those sums
  out <- which(test_stats[1L, ] == max(test_stats[1L, ]))
  # but after the second test (i.e. find the greatest number of categories), you should have one and only one combination left
  out[[which.max(test_stats[2L, out])]]
}

现在,我们使用一个函数来执行这两个步骤。

max_of_all_perm <- function(df, group_var, numer, categ) {
  l <- perm_all(df, group_var)
  l[[which_max(l, numer, categ)]]
}

并在pc定义的所有组中运行它

data %>% 
  nest(data = -pc) %>% 
  mutate(data = lapply(data, max_of_all_perm, "index", "g", "h")) %>% 
  unnest(data)

输出

# A tibble: 5 x 4
  pc    index     g     h
  <chr> <dbl> <dbl> <dbl>
1 A         1     2     1
2 A         2     6     2
3 A         3     7     3
4 B         4     8     3
5 B         5     9     3

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    • 2017-08-08
    • 2019-01-13
    • 1970-01-01
    • 2014-06-08
    • 1970-01-01
    • 2013-06-09
    相关资源
    最近更新 更多