我有一个'长格式'数据框,其中包含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
不幸的是,我不知道如何进行这种计算,而且在搜索建议时我画了一个空白(我怀疑,因为我不知道正确的术语)。
答案 0 :(得分:6)
这是一种类似于@mrdwab的data.table
方法
如果featureCode
为character
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
答案 1 :(得分: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
个featureCode
的{{1}}感兴趣:
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 .
答案 2 :(得分: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'
")
肯定有一些更简单的解决方案,特别是如果你有更多的组合需要考虑。也许搜索列联表可以帮助你。
答案 3 :(得分: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