【问题标题】:How to calculate a table of pairwise counts from long-form data frame如何从长格式数据框中计算成对计数表
【发布时间】:2012-11-01 11:05:00
【问题描述】:

我有一个“长格式”数据框,其中包含 id(主键)和 featureCode(分类变量)列。每条记录都有 1 到 9 个分类变量值。例如:

id  featureCode
5   PPLC
5   PCLI
6   PPLC
6   PCLI
7   PPL
7   PPLC
7   PCLI
8   PPLC
9   PPLC
10  PPLC

我想计算每个功能代码与其他功能代码一起使用的次数(标题的“成对计数”)。在这个阶段,每个特征码的使用顺序并不重要。我设想结果将是另一个数据框,其中行和列是特征代码,单元格是计数。例如:

      PPLC  PCLI  PPL
PPLC  0     3     1
PCLI  3     0     1
PPL   1     1     0

不幸的是,我不知道如何执行此计算,并且在搜索建议时我一直处于空白状态(我怀疑主要是因为我不知道正确的术语)。

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    这是一个类似于@mrdwab 的data.table 方法

    如果featureCodecharacter 效果最好

    library(data.table)
    
    DT <- data.table(dat)
    # convert to character
    DT[, featureCode := as.character(featureCode)]
    # subset those with >1 per id
    DT2 <- DT[, N := .N, by = id][N>1]
    # create all combinations of 2
    # return as a data.table with these as columns `V1` and `V2`
    # then count the numbers in each group
    DT2[, rbindlist(combn(featureCode,2, 
          FUN = function(x) as.data.table(as.list(x)), simplify = F)), 
        by = id][, .N, by = list(V1,V2)]
    
    
         V1   V2 N
    1: PPLC PCLI 3
    2:  PPL PPLC 1
    3:  PPL PCLI 1
    

    【讨论】:

    • 我一直在尝试这些方法,但无法超越您创建 DT2 的位置。
    • 我花了一段时间才意识到simplify = FALSE 是一个选项,然后才弄清楚如何返回正确维度 data.table 的时间。
    • 如果我想在数据中也包含 PPLC 到 PPLC 的计数怎么办
    【解决方案2】:

    如果您不需要确切的结构,而只需要获得成对计数,您可以尝试这种方法:

    这是您的数据:

    dat <- read.table(header = TRUE, 
           text = "id  featureCode
                    5         PPLC
                    5         PCLI
                    6         PPLC
                    6         PCLI
                    7          PPL
                    7         PPLC
                    7         PCLI
                    8         PPLC
                    9         PPLC
                   10         PPLC")
    

    我们只对有多个featureCodeids 感兴趣:

    dat2 <- dat[ave(dat$id, dat$id, FUN=length) > 1, ]
    

    将这些数据作为列表将很有用,因为它可以让我们使用lapply 来获得成对组合。

    dat2 <- split(dat2$featureCode, dat2$id)
    

    如果您愿意,可以将下一步分解为中间部分,但基本思想是在每个列表项中创建向量组合,然后将未列出的输出制成表格。

    table(unlist(lapply(dat2, function(x) 
      combn(sort(x), 2, FUN = function(y) 
        paste(y, collapse = "+")))))
    # 
    #  PCLI+PPL PCLI+PPLC  PPL+PPLC 
    #         1         3         1
    

    更新:另一个问题的更好答案

    稍加修改,@flodel 对another question 的回答适用于此处。它需要安装 igraph 包 (install.packages("igraph"))。

    dat2 <- dat[ave(dat$id, dat$id, FUN=length) > 1, ]
    dat2 <- split(dat2$featureCode, dat2$id)
    library(igraph)
    g <- graph.edgelist(matrix(unlist(lapply(dat2, function(x) 
      combn(as.character(x), 2, simplify = FALSE))), ncol = 2, byrow=TRUE), 
                        directed=FALSE)
    get.adjacency(g)
    # 3 x 3 sparse Matrix of class "dgCMatrix"
    #      PPLC PCLI PPL
    # PPLC    .    3   1
    # PCLI    3    .   1
    # PPL     1    1   .
    

    【讨论】:

      【解决方案3】:

      我会使用 SQL,在 R 中它可以通过 sqldf 包获得。

      提取所有可能的组合,例如:

      sqldf("select distinct df1.featureCode, df2.featureCode
             from df df1, df df2       
             ")
      

      然后你可以提取结果元素:
      (也许只对所有组合使用 for 循环)

      PCLI - PPLC

      sqldf("select count(df1.id)
             from df df1, df df2
             where df1.id = df2.id
             and df1.featureCode = 'PCLI' and df2.featureCode = 'PPLC'
             ")
      

      PPLC-PPL

      sqldf("select count(df1.id)
             from df df1, df df2
             where df1.id = df2.id
             and df1.featureCode = 'PPLC' and df2.featureCode = 'PPL'
             ")
      

      PCLI - PPL

      sqldf("select count(df1.id)
             from df df1, df df2
             where df1.id = df2.id
             and df1.featureCode = 'PCLI' and df2.featureCode = 'PPL'
             ")
      

      肯定有一些更简单的解决方案,特别是如果您需要考虑更多组合。也许搜索列联表可以帮助您。

      【讨论】:

      • 不幸的是,数据集中有 90 个左右的特征代码,因此手动创建组合会太耗时。不过,感谢您的建议。
      【解决方案4】:

      我认为另一种解决方案在概念上很容易理解。您在这里有一个二分图,只需将该图投影到“featureCode”顶点上即可。以下是使用 igraph 包执行此操作的方法:

      dat <- read.table(header = TRUE, stringsAsFactors=FALSE,
                        text = "id  featureCode                                       
                                5         PPLC                                                  
                                5         PCLI                                                  
                                6         PPLC                                                  
                                6         PCLI                                                  
                                7          PPL                                                  
                                7         PPLC                                                  
                                7         PCLI                                                  
                                8         PPLC                                                  
                                9         PPLC                                                  
                               10         PPLC")
      
      g <- graph.data.frame(dat, vertices=unique(data.frame(c(dat[,1], dat[,2]),
                                type=rep(c(TRUE, FALSE), each=nrow(dat)))))
      
      get.adjacency(bipartite.projection(g)[[1]], attr="weight", sparse=FALSE)
      
      #      PPLC PCLI PPL
      # PPLC    0    3   1
      # PCLI    3    0   1
      # PPL     1    1   0
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-06-30
        • 1970-01-01
        • 2021-10-27
        • 1970-01-01
        • 1970-01-01
        • 2013-03-19
        • 1970-01-01
        相关资源
        最近更新 更多