【问题标题】:How to remove duplicate rows based on three factor levels如何根据三个因子级别删除重复行
【发布时间】:2015-02-27 11:06:02
【问题描述】:

我参考了以下链接,似乎不适合我的问题。

Remove rows based on factor-levels

Remove row based on two factor levels

我有一个数据框,如下所示。

  ZNF226  1  A
  ZNF226  1  P
  ZNF227  1  M
  ZNF227  1  P
  ZNF229  1  P
  ZNF229  1  A
   ZNF23  1  M
  ZNF230  1  A
  ZNF232  1  P
  ZNF233  1  A
  ZNF233  1  P
  ZNF234  1  P
  ZNF235  1  A
  ZNF236  1  P
  ZNF236  1  P
  ZNF238  1  A
  ZNF238  1  M
  ZNF239  1  P
   ZNF24  1  A
   ZNF24  1  P
   ZNF24  1  P
   ZNF24  1  P

我想删除重复的行。我想在第三列中保留 P>A>M 偏好的行。如果 rows 具有 P,A,M 则仅保留具有 P 的行。如果 A 和 M 则 A 将在那里删除其他重复项,最后是 M。预期输出如下

  ZNF226  1  P
  ZNF227  1  P
  ZNF229  1  P
   ZNF23  1  M
  ZNF230  1  A
  ZNF232  1  P
  ZNF233  1  P
  ZNF234  1  P
  ZNF235  1  A
  ZNF236  1  P
  ZNF238  1  A
  ZNF239  1  P
   ZNF24  1  P

行数约为 70k。提前致谢。

已编辑:第一行和第二行上方是重复项。第一行第三列有A,第二行第三列有P。正如我提到的,首选将是P>A>M。所以 A 在 P 之后有第二个偏好。所以用A 删除行。

现在在第 3 和第 4 行。 P 优先保留,所以使用M 删除行

【问题讨论】:

    标签: r


    【解决方案1】:

    我们可以将data.table 用于大型数据集。将“data.frame”转换为“data.table”(setDT(df1))。按“V1”和“V2”分组,通过指定基于偏好的级别(“P > A > M”)将“V3”的类更改为因子。获取“V3”的“最小值”索引(which.min)并子集“V3”(V3[which.min(..)]

    library(data.table)
    setDT(df1)[, list(V3=V3[which.min(factor(V3, levels=c('P', 'A', 'M')))]),
                                       .(V1, V2)]
     #       V1 V2 V3
     #1: ZNF226  1  P
     #2: ZNF227  1  P
     #3: ZNF229  1  P
     #4:  ZNF23  1  M
     #5: ZNF230  1  A
     #6: ZNF232  1  P
     #7: ZNF233  1  P
     #8: ZNF234  1  P
     #9: ZNF235  1  A
    #10: ZNF236  1  P
    #11: ZNF238  1  A
    #12: ZNF239  1  P
    #13:  ZNF24  1  P
    

    dplyr类似的方法

    library(dplyr)
     df1 %>% 
        group_by(V1, V2) %>% 
        summarise(V3=V3[which.min(factor(V3, levels=c('P', 'A', 'M')))])
    

    更新

    基于新数据集

    df2 <- read.csv('111.csv', header=TRUE, stringsAsFactors=FALSE)
    str(df2)
    #'data.frame':  2618 obs. of  4 variables:
    # $ X : int  1 2 3 4 5 6 7 8 9 10 ...
    # $ V1: chr  "A1BG" "A1BG-AS" "A1CF" "A2LD1" ...
    # $ V2: int  1 1 1 1 1 1 1 1 1 1 ...
    # $ V3: chr  "P" "A" "A" "A" ...
    res <-  setDT(df2)[, list(V3=V3[which.min(factor(V3,
               levels=c('P', 'A', 'M')))]), .(V1, V2)]
    dim(res)
    #[1] 1175    3
    

    如果我们需要在 R 控制台打印所有数据集的行,请更改 options

      op <- options(datatable.print.nrows=Inf)
      res[1:10,]
    

    数据

    df1 <- structure(list(V1 = c("ZNF226", "ZNF226", "ZNF227", "ZNF227", 
    "ZNF229", "ZNF229", "ZNF23", "ZNF230", "ZNF232", "ZNF233", "ZNF233", 
    "ZNF234", "ZNF235", "ZNF236", "ZNF236", "ZNF238", "ZNF238", "ZNF239", 
    "ZNF24", "ZNF24", "ZNF24", "ZNF24"), V2 = c(1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L), V3 = c("A", "P", "M", "P", "P", "A", "M", "A", "P", "A", 
    "P", "P", "A", "P", "P", "A", "M", "P", "A", "P", "P", "P")),
    .Names =  c("V1", "V2", "V3"), class = "data.frame", 
    row.names = c(NA, -22L))
    

    【讨论】:

    • 它给了我一半的结果。 M 不确定我是否遗漏了什么。
    • @dssunilkumar 根据输入数据集,我的解决方案得到了您所展示的预期结果
    • 你说得对。你能检查一下这个文件dropbox.com/s/tynca5hm2vu0f0t/111.csv?dl=0
    • @dssunilkumar 我不确定新数据集的预期输出是什么。我使用代码得到 1175 行
    • 你能不能把那个文件给我。
    【解决方案2】:

    将 1,2,3 分别赋值给 M,A,P,如:

    df$x[df$col3 == "M"] <- 1
    df$x[df$col3 == "A"] <- 2
    df$x[df$col3 == "P"] <- 3
    

    然后按列 1 和 2 使用聚合

    df <- aggregate(df$x, list(df$col1, df$col2), max)
    

    然后将数字还原为相应的字母。

    你提供的例子,读起来很粗糙:

    df <- read.table(text = "
    ZNF226  1  A
    ZNF226  1  P
    ZNF227  1  M
    ZNF227  1  P
    ZNF229  1  P
    ZNF229  1  A
    ZNF23  1  M
    ZNF230  1  A
    ZNF232  1  P
    ZNF233  1  A
    ZNF233  1  P
    ZNF234  1  P
    ZNF235  1  A
    ZNF236  1  P
    ZNF236  1  P
    ZNF238  1  A
    ZNF238  1  M
    ZNF239  1  P
    ZNF24  1  A
    ZNF24  1  P
    ZNF24  1  P
    ZNF24  1  P", sep = " ", header = F)
    
    df <- df[-c(2,4)]
    colnames(df) <- c("col1", "col2", "col3")
    
    df$x[df$col3 == "M"] <- 1
    df$x[df$col3 == "A"] <- 2
    df$x[df$col3 == "P"] <- 3
    
    df <- aggregate(df$x, list(df$col1, df$col2), max)
    colnames(df) <- c("col1", "col2", "col3")
    
    df$col3[df$col3 == 1] <- "M"
    df$col3[df$col3 == 2] <- "A"
    df$col3[df$col3 == 3] <- "P"
    

    然后输出:

    > df
         col1 col2 col3
    1  ZNF226    1    P
    2  ZNF227    1    P
    3  ZNF229    1    P
    4   ZNF23    1    M
    5  ZNF230    1    A
    6  ZNF232    1    P
    7  ZNF233    1    P
    8  ZNF234    1    P
    9  ZNF235    1    A
    10 ZNF236    1    P
    11 ZNF238    1    A
    12 ZNF239    1    P
    13  ZNF24    1    P
    > 
    

    【讨论】:

    • 是的,它应该可以工作。要我为你做一个可重现的例子吗?
    • 如果你能请,那就太好了
    • 给我这个错误:$&lt;-.data.frame(*tmp*, "x", value = numeric(0)) 中的错误:替换有 0 行,数据有 695
    • 在运行完整数据框或运行我的示例时是否会出错?
    猜你喜欢
    • 2012-06-23
    • 1970-01-01
    • 1970-01-01
    • 2019-06-22
    • 2017-11-26
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    • 2013-10-29
    相关资源
    最近更新 更多