【问题标题】:group by column and identify key rows按列分组并识别关键行
【发布时间】:2020-01-15 06:23:58
【问题描述】:

我把问题一分为二:

问题1: 我有一个矩阵(Mat1,Mat2)的列表(list1)。每个矩阵具有相同的维度但不同的元素。对于每个矩阵,我需要按“数字”对数据进行分组,然后转到“分数”。我需要确定得分最高的行。我想将此行号存储在名为 output1 的列表中。我想将所有其他行号存储在名为 output2 的列表中。重要提示:我不想存储行本身。我想存储行号

问题2:与问题1相同。但是,在这种情况下,我按数字对数据进行分组,然后移动到“分数”并找到前两个数字的行。

设置:

set.seed(4)
Mat1 <- data.frame(matrix(nrow=508, ncol =4))
Mat1[,1] <- c(rep(1,20), rep(NA, 508-20))
Mat1[1:20,2:4] <- rnorm(20*3,0,1)


Mat2 <- data.frame(matrix(nrow=508, ncol =4))
Mat2[,1] <- c(rep(c(1,2,3,4,5),5), rep(NA, 508-25))
Mat2[1:30,2:4] <- rnorm(30*3,0,1)


colnames(Mat1)[1:2] = colnames(Mat2)[1:2] = c("number", "score")
list1 <- list(Mat1, Mat2)


Mat1
    number       score         X3          X4
1        1  0.21675486  1.5408150  1.34370863
2        1 -0.54249257  0.1651690  0.18153538
3        1  0.89114465  1.3076224  1.29251234
4        1  0.59598058  1.2882569 -1.68804858
5        1  1.63561800  0.5928969 -0.82099358
6        1  0.68927544 -0.2829437 -0.86214614
7        1 -1.28124663  1.2558840  0.09884369
8        1 -0.21314452  0.9098392 -0.37565514
9        1  1.89653987 -0.9280281  0.72390416
10       1  1.77686321  1.2401808 -1.79738202
11       1  0.56660450  0.1534642 -0.66374314
12       1  0.01571945  1.0519326 -0.62372649
13       1  0.38305734 -0.7542112 -0.07963243
14       1 -0.04513712 -1.4821891  0.43562476
15       1  0.03435191  0.8611319  1.97090097
16       1  0.16902677 -0.4045198 -0.59675867
17       1  1.16502684 -0.2274054 -0.55250721
18       1 -0.04420400  0.9340962  0.69596663
19       1 -0.10036844 -0.4658959 -0.15566396
20       1 -0.28344457 -0.6375435  1.34889820

所以 Mat 1 有一组对应于 number =1。我想按“数字”对数据进行分组并识别具有最大值的行(对于 Mat1,这将是第 9 行)。然后我想将数字 9 存储在名为 Output1 的列表中。然后,Output2[[1]] 将包含 507 (508-1) 个元素,因此,除了行号 9 之外的所有行号。

然后我想对 Mat2 重复这个过程。 Output1[[2]] 应该由元素组成(因为“数字”有 5 个组。数字可以 = 1、2、3、4 或 5。)

我想对集合中的所有矩阵重复此过程。在我的应用程序中,我的集合中有大量矩阵。

【问题讨论】:

  • 对于 Problem1 output1 &lt;- lapply(list1,. %&gt;% group_by(`number`) %&gt;% slice(which.max(`score`))) 已接近。但是,它存储实际行并将 NA 视为分组依据(不应该是这种情况)
  • 您要从Output1Output2 中删除所有NA 值吗?
  • @RonakShah 澄清:Output1[[1]] 应该有 1 个元素(无 NA)。 Output1[[2]] 应该有 5 个元素(无 NA)。 Output2[[1]] 应该有 507 个元素(无 NA),Output2[[2]] 应该有 508-5 个元素(无 NA)。这清楚吗?
  • 是的,但是如果您检查可重现的示例,您将在第一个矩阵中从第 21 行到第 508 行获得所有 NA 值。前 10 个检查 list1[[1]][21:30, ]。我不确定您将如何获得具有 507 个元素且没有 NAs 的 Output2[[1]]
  • @RonakShah 该代码存储了实际的数据行。这次我只想要“行号”。不是存储的整行。

标签: r matrix group-by dplyr


【解决方案1】:

使用data.table 可以轻松完成分组和子集化。

library(data.table)

lapply(list1, function(x) {

    setDT(x)

    # add row numbers to grouped data.table
    x[, rownum := .I]

    # add a coulmn indicating row(s) with max score for each group
    x[, maxscore := (score==max(score)), by=number]

    # exclude NAs

    maxrows <- x[maxscore==TRUE][!is.na(number)]
    otherrows <- x[maxscore==FALSE]

    # get those row numbers
    list(
        output1 = maxrows$rownum,
        output2 = otherrows$rownum
    )
})

注意几点:

  • 如果相同的最高分在一个组中出现两次,这样您将获得该值出现的所有行 - 相反,如果您只对分组行排序并选择第一个行,您会错过可能具有相同最高分值的其他行

  • 您可以一次性获得 output1 和 output2 - 对我来说,这比循环两次更有意义 - 您可以稍后从输出中选择您想要的任何元素,并将它们作为两个单独的列表获取,如果这是您的需要

【讨论】:

    【解决方案2】:

    我们可以使用dplyrpurrr 来获取output1output2 中的行索引

    library(purrr)
    library(dplyr)
    
    output1 <- map(list1, ~ .x %>% na.omit %>%
                            mutate(row = row_number()) %>%
                            group_by(number) %>% 
                            summarise(max = row[which.max(score)]) %>% 
                            pull(max))
    
    
    output2 <- map2(map(list1, ~seq_len(nrow(.x))), output1, setdiff)
    

    【讨论】:

      猜你喜欢
      • 2016-12-12
      • 1970-01-01
      • 2013-10-31
      • 2013-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多