4

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

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

4

4 回答 4

8

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

如果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
于 2012-11-01T22:37:39.087 回答
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")

我们只对id有多个 s 的 s感兴趣featureCode

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 对另一个问题的回答在这里适用。它需要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   .
于 2012-11-01T18:41:18.180 回答
1

我会使用 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'
       ")

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

于 2012-11-01T13:24:57.047 回答
1

我认为另一种解决方案在概念上很容易理解。您在这里有一个二分图,只需将该图投影到“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
于 2012-11-05T03:12:57.257 回答