我的data.frame如下:
group_id user_id
1000 26
1236 29
1236 46
3767 26
3767 46
5614 29
5614 45
5614 46
我需要输出如下:
User-1 User-2 #of-common-groups
26 26 2
26 46 1
29 29 2
29 45 1
29 46 2
45 29 1
45 45 1
45 46 1
46 26 1
46 29 2
46 45 1
46 46 3
有没有快速实现这一目标的方法?我实际上有137个不同的组和大约81000个用户。
用户26属于2组,并且他还与用户46共享相同的组3767。因此
26 26 2
26 46 1
46 26 1
46 46 3 (user 46 belongs to 3 groups) etc
答案 0 :(得分:3)
# your data
dat <- read.table(text="group_id user_id
1000 26
1236 29
1236 46
3767 26
3767 46
5614 29
5614 45
5614 46", header=T)
# convert to matrix
m <- as.matrix(table(dat))
#calculate and rehape
mm <- crossprod(m,m)
r <- reshape2::melt(mm)
# remove where zero counts
r[r$value !=0 ,]
# user_id user_id value
# 1 26 26 2
# 4 46 26 1
# 6 29 29 2
# 7 45 29 1
# 8 46 29 2
# 10 29 45 1
# 11 45 45 1
# 12 46 45 1
# 13 26 46 1
# 14 29 46 2
# 15 45 46 1
# 16 46 46 3
编辑:来自Network: Making Graph Object from Event-Node Data Using igraph的想法
g <- graph.data.frame(dat, directed = FALSE)
V(g)$type <- V(g)$name %in% unique(as.character(dat$group_id))
b <- bipartite.projection(g)$proj1
ad <- get.adjacency(b, sparse=F, attr="weight")
ad <- ad[sort(colnames(ad)), sort(colnames(ad))]
diag(ad) <- colSums(table(dat))
then continue as before
答案 1 :(得分:3)
怎么样:
df <- read.table(text="group_id user_id
1000 26
1236 29
1236 46
3767 26
3767 46
5614 29
5614 45
5614 46", header=T)
df <- merge(df, df, by = "group_id")[,-1]
library(plyr)
ddply(df,.(user_id.x, user_id.y),nrow)
user_id.x user_id.y V1
1 26 26 2
2 26 46 1
3 29 29 2
4 29 45 1
5 29 46 2
6 45 29 1
7 45 45 1
8 45 46 1
9 46 26 1
10 46 29 2
11 46 45 1
12 46 46 3
修改强>
在这种情况下,我担心这很简单,因为merge
有一个&#34;大&#34;用户数和少量组。根据最终用途的不同,我会考虑用户20650已经建议的图形结构,并且可能保持原样。在许多情况下,快速查找顶点(user.id)的无向加权图似乎是一个很好的解决方案。
如果数据集较小(或重叠次数较少),我会留下这个简单的方法。
答案 2 :(得分:3)
这是尝试使用Matrix
套餐 - 只是复制@ nograpes&#39;来自here的答案:
require(Matrix)
sm = sparseMatrix(dat$group_id, dat$user_id, x = TRUE)
cp = t(sm) %*% sm
as.data.frame(summary(cp))
# i j x
# 1 26 26 2
# 2 46 26 1
# 3 29 29 2
# 4 45 29 1
# 5 46 29 2
# 6 29 45 1
# 7 45 45 1
# 8 46 45 1
# 9 26 46 1
# 10 29 46 2
# 11 45 46 1
# 12 46 46 3
答案 3 :(得分:2)
所以这里有两种方法,一种使用data.table
...
library(data.table)
setkey(setDT(df),group_id)
df[df,allow.cartesian=TRUE][,.N,by=list(user_id,i.user_id)][order(user_id,i.user_id)]
# user_id i.user_id N
# 1: 26 26 2
# 2: 26 46 1
# 3: 29 29 2
# 4: 29 45 1
# 5: 29 46 2
# 6: 45 29 1
# 7: 45 45 1
# 8: 45 46 1
# 9: 46 26 1
# 10: 46 29 2
# 11: 46 45 1
# 12: 46 46 3
和一个使用sqldf
...
library(sqldf)
sqldf("select a.user_id as user1, b.user_id as user2, count(*) as groups
from df a inner join df b on a.group_id=b.group_id
group by 1,2 order by 1,2")
# user1 user2 groups
# 1 26 26 2
# 2 26 46 1
# 3 29 29 2
# 4 29 45 1
# 5 29 46 2
# 6 45 29 1
# 7 45 45 1
# 8 45 46 1
# 9 46 26 1
# 10 46 29 2
# 11 46 45 1
# 12 46 46 3
data.table方法可能会更快,但您的数据集不是很大,所以它可能不会产生太大差异。