代码之家  ›  专栏  ›  技术社区  ›  ip2018

删除R中数据帧中重复单元格(不是整行/列)的所有实例

  •  1
  • ip2018  · 技术社区  · 7 年前

    genes_1 = c("a","b","c","d","e")
    genes_2 = c("f","g","c","e","j")
    genes_3 = c("a","b","m","n","o")
    df = data.frame(genes_1, genes_2, genes_3)
    

    我想要的输出:

    genes_1 = c("","","","d","")
    genes_2 = c("f","g","","","j")
    genes_3 = c("","","m","n","o")
    df = data.frame(genes_1, genes_2, genes_3)
    

    谢谢

    3 回复  |  直到 7 年前
        1
  •  4
  •   hrbrmstr    7 年前

    data.frame(
      genes_1 = c("a","b","c","d","e"),
      genes_2 = c("f","g","c","e","j"),
      genes_3 = c("a","b","m","n","o"),
      stringsAsFactors = FALSE
    ) -> xdf
    
    dups <- names(which(table(unlist(xdf, use.names = FALSE)) > 1))
    
    xdf[] <- lapply(xdf, function(x) { x[x %in% dups] <- "" ; x })
    
    xdf
    

    unlist() 递归地将所有列展开为单个字符向量。

    table() 计算每个元素的所有出现次数。

    which() TRUE

    names() 获取角色选择向量元素。

    ""

    library(microbenchmark)
    library(data.table)
    
    microbenchmark(
      base = {
        ydf <- xdf
        dups <- names(which(table(unlist(ydf, use.names = FALSE)) > 1))
        ydf[] <- lapply(ydf, function(x) { x[x %in% dups] <- "" ; x })
      },
      base.2 = {
        ydf <- xdf
        tmp <- unlist(ydf)
        ydf[arrayInd(which(duplicated(tmp) | duplicated(tmp, fromLast = TRUE)), dim(ydf))] <- ""
      },
      tidyverse = {
        ydf <- xdf
        ydf %>%
          gather(genes, value) %>%
          add_count(value) %>%
          mutate(value = ifelse(n > 1, "", value)) %>%
          select(-n) %>%
          group_by(genes) %>%
          mutate(ID = 1:n()) %>%
          spread(genes, value) %>%
          select(-ID) -> ydf
      },
      data.table = {
        ydt <- data.table(xdf)
        ydt[,lapply(.SD, function(x) { x[x %in% dups] <- "" ; x })]
      }
    ) %>%
      { print(.) ; . } %>% 
      autoplot()
    

    enter image description here

        2
  •  3
  •   thelatemail    7 年前

    另一种基本解决方案:

    tmp <- unlist(df)
    df[arrayInd(which(duplicated(tmp) | duplicated(tmp,fromLast=TRUE)), dim(df))] <- NA
    
    #  genes_1 genes_2 genes_3
    #1    <NA>       f    <NA>
    #2    <NA>       g    <NA>
    #3    <NA>    <NA>       m
    #4       d    <NA>       n
    #5    <NA>       j       o
    

    unlist 只需为中的所有值创建一个长向量 df
    arrayInd 然后为子集创建一个两列的行/列索引 测向 duplicated 价值观。

        3
  •  2
  •   www    7 年前

    tidyverse 解决方案。 df2 是最终输出。

    library(tidyverse)
    
    df2 <- df %>%
      gather(genes, value) %>%
      add_count(value) %>%
      mutate(value = ifelse(n > 1, "", value)) %>%
      select(-n) %>%
      group_by(genes) %>%
      mutate(ID = 1:n()) %>%
      spread(genes, value) %>%
      select(-ID)