如何从R中的数据框创建不同格式的矩阵?

时间:2015-01-03 21:48:58

标签: r matrix

我的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

4 个答案:

答案 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方法可能会更快,但您的数据集不是很大,所以它可能不会产生太大差异。