【问题标题】:Finding rows with a unique combination of values (R)查找具有唯一值组合的行 (R)
【发布时间】:2020-03-22 07:35:18
【问题描述】:

这个标题有点复杂,我敢肯定,如果我能想出一种更好地描述它的方法,我可以更好地用谷歌搜索它。

我的数据如下所示:

SET                     ID    
100301006              1287025
100301006              1287026
100301010              1287027
100301013              1287030
100301011              1287027

并且我想识别并选择那些行中的每个值都具有该列的唯一值的行。在上面的示例中,我只想抓取行:

100301013              1287030

我不想要 SET100301006,因为它匹配 ID 字段中的 2 个不同记录(1287025 和 1287026)。同样,我不想要 SET 100301010,因为它与 (1287027) 匹配的 ID 记录也可以匹配另一个 SET (10030011)。

在某些情况下,匹配项可能超过 2 个。

我可以循环执行此操作,但这似乎是一种 hack。我想要一个基本的 R 或 data.table 解决方案,但我对 dplyr 不太感兴趣(试图最小化依赖关系)。

【问题讨论】:

    标签: r dataframe data.table


    【解决方案1】:

    我们可以在每一列上独立地使用duplicated 来创建逻辑vectors 的list,将Reduce 与& 一起使用为单个向量,并使用它来对数据集的行进行子集化

    df1[Reduce(`&`, lapply(df1, function(x) 
             !(duplicated(x)|duplicated(x, fromLast = TRUE)))),]
    #     SET      ID
    #4 100301013 1287030
    

    或如@chinsoon12 建议的那样

     m1 <- sapply(df1, function(x) !(duplicated(x)| duplicated(x, fromLast = TRUE)))
     df1[rowSums(m1) == ncol(m1),, drop = FALSE]
    

    数据

    df1 <- structure(list(SET = c(100301006L, 100301006L, 100301010L, 100301013L, 
    100301011L), ID = c(1287025L, 1287026L, 1287027L, 1287030L, 1287027L
    )), class = "data.frame", row.names = c(NA, -5L))
    

    【讨论】:

      【解决方案2】:

      这是一个快速的 base-R hack:

      df <- read.table(header = TRUE, stringsAsFactors = FALSE, text = "
      SET                     ID    
      100301006              1287025
      100301006              1287026
      100301010              1287027
      100301013              1287030
      100301011              1287027")
      
      counts <- sapply(df, function(x) { tb <- table(x); tb[ match(x, names(tb)) ]; })
      counts
      #           SET ID
      # 100301006   2  1
      # 100301006   2  1
      # 100301010   1  2
      # 100301013   1  1
      # 100301011   1  2
      

      此时,我们有在其列中找到每个元素的次数......所以我们想要所有计数都为 1 的行。

      df[ rowSums(counts == 1) == ncol(df), ]
      #         SET      ID
      # 4 100301013 1287030
      

      【讨论】:

        【解决方案3】:

        您可以使用 data.table 仅选择具有 1 行的组,首先按 ID 分组,然后按 SET 分组。这类似于@r2evans 检查 ID 和 SET 的计数是否均为 1 的方法。

        library(data.table)
        setDT(df)
        
        df[, if(.N == 1) .SD, ID][, if(.N == 1) .SD, SET]
        
        #          SET      ID
        # 1: 100301013 1287030
        

        或超过 2 列

        Reduce(function(x, y) x[, if(.N == 1) .SD, y], names(df), init = df)
        #         ID       SET
        # 1: 1287030 100301013
        

        【讨论】:

          【解决方案4】:

          有了base R,或许你可以用ave()来实现:

          r <-df[which(with(df,ave(seq(nrow(df)),SET,FUN = length)*ave(seq(nrow(df)),ID,FUN = length)) == 1),]
          > r
                  SET      ID
          4 100301013 1287030
          

          数据

          df <- read.table(text="SET                     ID    
          100301006              1287025
          100301006              1287026
          100301010              1287027
          100301013              1287030
          100301011              1287027",header = T)
          
          

          【讨论】:

          • 感谢所有回复的人。我选择了@ThomasIsCoding 的回复,因为我觉得它最易读。
          【解决方案5】:

          如果我们有一个数据框df 并且想要查找列的唯一值:column1、column2、column3:

          library(dplyr)
          df <- df %>% group_by(column1,column2,column3) %>% summarise()
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-04-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-06-01
            相关资源
            最近更新 更多