【问题标题】:Calculate overlap between binary variables计算二元变量之间的重叠
【发布时间】:2020-08-23 21:00:59
【问题描述】:

我正在尝试计算有多少人参加了不同的运动组合。我知道如何计算和绘制相关性,但我想知道每个组合组中有多少人的实际数量。

这是我的数据的简化演示。 1 表示某个人参加某项运动,0 表示她不参加。

    sports_example <- tibble(
      name = c(
        "Scarlett",
        "Heather",
        "Sarah",
        "Anna",
        "Emma",
        "Charlotte",
        "Cheryl"
      ),
      hockey = c(1L, 1L, 1L, 1L, 0L, 1L, 1L),
      basketball = c(0L, 1L, 1L, 0L, 1L, 1L, 0L),
      track = c(1L, 1L, 1L, 0L, 1L, 0L, 1L),
      football = c(0L, 1L, 0L, 0L, 0L, 0L, 0L)
    )

使用下面的代码,我可以计算不同运动之间的相关性。我可以说曲棍球与篮球相比,与足球分享的球员更多。但我想计算 有多少 运动员同时打曲棍球和篮球(在本例中为 3)。是否有一个简单的算法来计算重叠?我的真实数据集有几十列,所以我的一次性代码没有剪切它(例如nrow(filter(sports_example, hockey + basketball == 2)))。

sports_example %>% 
  select(-name) %>% 
  cor() %>% 
  corrgram::corrgram(upper.panel = NULL)

【问题讨论】:

    标签: r correlation


    【解决方案1】:

    如果您追求成对结果,您可以堆叠数据并使用crossprod()

    spex <- subset(cbind(sports_example[1], stack(sports_example[-1])),values == 1)
    res <- crossprod(table(spex$name, spex$ind))
    res[upper.tri(res, diag = TRUE)] <- 0
    
    subset(as.data.frame.table(res), Freq > 0)
    
             Var1       Var2 Freq
    2  basketball     hockey    3
    3       track     hockey    4
    4    football     hockey    1
    7       track basketball    3
    8    football basketball    1
    12   football      track    1
    

    【讨论】:

    • 很多很好的答案,但我选择了你的,因为它是最灵活的方法,而且无论我如何更改基础数据,它似乎都同样有效。谢谢!
    【解决方案2】:

    我建议下一种方法,您可以确定所有玩家会发生什么:

    library(reshape2)
    library(tibble)
    library(dplyr)
    
    #Data
    sports_example <- tibble(
      name = c(
        "Scarlett",
        "Heather",
        "Sarah",
        "Anna",
        "Emma",
        "Charlotte",
        "Cheryl"
      ),
      hockey = c(1L, 1L, 1L, 1L, 0L, 1L, 1L),
      basketball = c(0L, 1L, 1L, 0L, 1L, 1L, 0L),
      track = c(1L, 1L, 1L, 0L, 1L, 0L, 1L),
      football = c(0L, 1L, 0L, 0L, 0L, 0L, 0L)
    )
    
    #Reshape
    Melted <- melt(sports_example,id.vars = 'name')
    

    重塑后,您可以使用dplyr 函数进行分组和聚合:

    #Now filter and compute
    Melted %>% group_by(name) %>% filter(variable %in% c('hockey','basketball')) %>% 
      summarise(N=sum(value))
    

    这将导致:

    # A tibble: 7 x 2
      name          N
      <chr>     <int>
    1 Anna          1
    2 Charlotte     2
    3 Cheryl        1
    4 Emma          1
    5 Heather       2
    6 Sarah         2
    7 Scarlett      1
    

    然后你可以添加一个新的过滤器来达到你想要的效果:

    #Now filter and compute 2
    Melted %>% group_by(name) %>% filter(variable %in% c('hockey','basketball')) %>% 
      summarise(N=sum(value)) %>% filter(N==2)
    

    输出:

    # A tibble: 3 x 2
      name          N
      <chr>     <int>
    1 Charlotte     2
    2 Heather       2
    3 Sarah         2
    

    然后,您还可以识别玩家和您想要的号码。

    【讨论】:

      【解决方案3】:

      count()怎么样?

      count(sports_example, hockey, basketball)
      ##   hockey basketball     n
      ##    <int>      <int> <int>
      ## 1      0          1     1
      ## 2      1          0     3
      ## 3      1          1     3
      

      或者

      (count(sports_example, hockey, basketball) 
         %>% filter(hockey==1, basketball==1)
         %>% pull(n)
      )
      

      base-R 版本类似于

      with(sports_example, as.data.frame(table(hockey,basketball)))
      

      【讨论】:

        【解决方案4】:

        获取长格式数据,仅保留value = 1 的行,为每个namecount 创建配对组合。

        library(dplyr)
        
        sports_example %>%
          tidyr::pivot_longer(cols = -name, names_to = 'col') %>%
          filter(value == 1) %>%
          group_by(name) %>%
          summarise(val = if(n() > 1) combn(col, 2, function(x) 
                             sort(toString(x))) else col) %>%
          ungroup %>%
          count(val)
        
        #  val                      n
        #  <chr>                <int>
        #1 basketball, football     1
        #2 basketball, track        3
        #3 hockey                   1
        #4 hockey, basketball       3
        #5 hockey, football         1
        #6 hockey, track            4
        #7 track, football          1
        

        此答案适用于dplyr > 1.0.0,它允许在summarise 中返回多行。

        【讨论】:

          【解决方案5】:

          你可以矢量化:

          (sports_example$hockey & sports_example$basketball) %>% sum
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-01-28
            • 1970-01-01
            • 1970-01-01
            • 2018-11-16
            • 1970-01-01
            • 2023-01-19
            • 2021-07-23
            • 1970-01-01
            相关资源
            最近更新 更多