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

如何在数据帧中查找组之间共享的值?

  •  0
  • divibisan  · 技术社区  · 6 年前

    我有一个整洁的data.frame,有两列: exp val . 我想找出 在所有不同的实验中共享。

    df <- data.frame(exp = c('A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'C', 'C'),
                     val = c(10, 20, 15, 10, 10, 15, 99, 2, 15, 20, 10, 4))
    df
    
       exp val
    1    A  10
    2    A  20
    3    A  15
    4    A  10
    5    B  10
    6    B  15
    7    B  99
    8    B   2
    9    C  15
    10   C  20
    11   C  10
    12   C   4
    

    预期结果可以是值向量:

    10, 15
    

    或数据帧上的列,指示该值是否共享:

       exp     val shared
       <fct> <dbl> <lgl> 
     1 A        10 TRUE  
     2 A        20 FALSE 
     3 A        15 TRUE  
     4 A        10 TRUE  
     5 B        10 TRUE  
     6 B        15 TRUE  
     7 B        99 FALSE 
     8 B         2 FALSE 
     9 C        15 TRUE  
    10 C        20 FALSE 
    11 C        10 TRUE  
    12 C         4 FALSE 
    

    我能找到答案(见下面的自我答案),但这似乎是一个很常见的问题 必须 做一个比我想出的老套解决方案更好的方法。

    dplyr 因为这是我所熟悉的,但我对任何解决方案都感兴趣。

    4 回复  |  直到 6 年前
        1
  •  2
  •   akuiper    6 年前

    或者你可以分组 val 然后检查 exp 为了这个 等于distinct的数据帧级别数 经验

    df %>% 
        group_by(val) %>% 
        mutate(shared = n_distinct(exp) == n_distinct(.$exp))
        # notice the first exp refers to exp for each group while .$exp refers 
        # to the overall exp column in the data frame
    
    # A tibble: 12 x 3
    # Groups:   val [6]
    #   exp     val shared
    #   <fct> <dbl> <lgl> 
    # 1 A        10 TRUE  
    # 2 A        20 FALSE 
    # 3 A        15 TRUE  
    # 4 A        10 TRUE  
    # 5 B        10 TRUE  
    # 6 B        15 TRUE  
    # 7 B        99 FALSE 
    # 8 B         2 FALSE 
    # 9 C        15 TRUE  
    #10 C        20 FALSE 
    #11 C        10 TRUE  
    #12 C         4 FALSE
    
        2
  •  2
  •   Onyambu    6 年前

    使用基R可以使用 table :

    as.numeric(colnames(a<-table(df))[colSums(a>0)==nrow(a)])
    [1] 10 15
    

    您还可以执行以下操作:

    df %>%
       mutate(s = val %in% as.numeric(colnames(a<-table(df))[colSums(a>0)==nrow(a)]))
       exp val     s
    1    A  10  TRUE
    2    A  20 FALSE
    3    A  15  TRUE
    4    A  10  TRUE
    5    B  10  TRUE
    6    B  15  TRUE
    7    B  99 FALSE
    8    B   2 FALSE
    9    C  15  TRUE
    10   C  20 FALSE
    11   C  10  TRUE
    12   C   4 FALSE
    
        3
  •  2
  •   johannes    6 年前

    下面是另一个基本R解决方案:

    x <- split(df$val, df$exp)
    Reduce(intersect, x)
    ## [1] 10 15
    
        4
  •  0
  •   divibisan    6 年前

    我们可以逐行遍历data.frame并计算在向量中找到该行值的次数 df$val .

    为了处理可能的重复值,我们必须使用 group_by %>% distinct val 在小组内。但是为了得到 瓦尔 ungroup %>% select(val) %>% unlist ,这似乎不必要地复杂。

    最后,我们可以检查值所在的组数是否等于组总数。

    df %>%
        rowwise() %>%
        mutate(num_groups = sum(group_by(., exp) %>%
                                    distinct(val) %>%
                                    ungroup() %>%
                                    select(val) %>%
                                    unlist() %in% val),
               shared = num_groups == length(unique(.$exp)))
    
    
    # A tibble: 12 x 4
       exp     val num_groups shared
       <fct> <dbl>      <int> <lgl> 
     1 A        10          3 TRUE  
     2 A        20          2 FALSE 
     3 A        15          3 TRUE  
     4 A        10          3 TRUE  
     5 B        10          3 TRUE  
     6 B        15          3 TRUE  
     7 B        99          1 FALSE 
     8 B         2          1 FALSE 
     9 C        15          3 TRUE  
    10 C        20          2 FALSE 
    11 C        10          3 TRUE  
    12 C         4          1 FALSE