在R或MySQL中创建跨频率表

时间:2015-06-08 01:11:33

标签: mysql r

我有一个user_id表 - 类别对。用户可以分为多个类别。我试图为每个可能的结果计算跨类别。即属于A类和C类的用户数量等。

我的原始数据结构如下:

example results

我希望看起来像这样的结果,显示跨类别的计数:

example results

如何在R或MySQL中完成?数据非常大。

以下是样本数据:

data <- structure(list(category = structure(c(1L, 2L, 2L, 1L, 3L, 3L, 
2L, 1L, 3L, 2L, 2L, 2L, 3L, 1L, 1L, 3L), .Label = c("A", "B", 
"C"), class = "factor"), user_id = c(464L, 345L, 342L, 312L, 
345L, 234L, 423L, 464L, 756L, 756L, 345L, 345L, 464L, 345L, 234L, 
312L)), .Names = c("category", "user_id"), class = "data.frame", row.names = c(NA, 
-16L))

任何代码片段,关于方法,功能或包装建议的想法都将受到赞赏。谢谢! -John

4 个答案:

答案 0 :(得分:2)

在R中,我会首先通过用户分割数据,为该用户计算所有唯一的类别对然后分组在一起来实现这一点:

data$category <- as.character(data$category)
(combos <- do.call(rbind, tapply(data$category, data$user_id, function(x) {
  u <- unique(x)
  if (length(u) > 1) t(combn(u, 2))
  else NULL
})))
#      [,1] [,2]
# [1,] "C"  "A" 
# [2,] "A"  "C" 
# [3,] "B"  "C" 
# [4,] "B"  "A" 
# [5,] "C"  "A" 
# [6,] "A"  "C" 
# [7,] "C"  "B" 

最后一步是将对列表制表,这可以通过R中的table函数来完成。我们实际上会使用table两次来捕获(a,b)和(b,a )对于类别a和b的每个配对:

table(combos[,1], combos[,2]) + table(combos[,2], combos[,1])
#     A B C
#   A 0 1 4
#   B 1 0 2
#   C 4 2 0

答案 1 :(得分:1)

基于提供的示例数据,我实际上并不认为@josilber提供的R解决方案是正确的,但是由于缺少所需的示例解决方案,我可能会错。我认为您可以使用igraph及其数据的二分网络表示来实现此目的,但这对于较大的数据/类别集可能效率低下。作为替代方案,可以使用数据的稀疏矩阵表示在R中进行相对有效的计算,如下所示:

library('Matrix')
mat <- spMatrix(nrow=length(unique(data$category)),
    ncol=length(unique(data$user_id)),
    i = as.numeric(factor(data$category)),
    j = as.numeric(factor(data$user_id)),
    x = rep(1, length(as.numeric(data$category)))
)
rownames(mat) <- levels(factor(data$category))
colnames(mat) <- levels(factor(data$user_id))
mat

#mat_row <- mat %*% t(mat)

##  Based on @user20650's comment this is even more efficient than
##    the multiplication above:
mat_row <- tcrossprod(mat)

我认为根据上面的示例数据得出以下正确的输出:

> mat_row
3 x 3 sparse Matrix of class "dgCMatrix"
  A  B C
A 7  3 5
B 3 12 4
C 5  4 5

答案 2 :(得分:0)

在MySQL中,您可以使用三列格式轻松完成此操作:

select a.category, b.category, count(*)
from pairs a join
     pairs b
     on a.user_id = b.user_id
group by a.category, b.category;

在SQL中生成表作为矩阵具有挑战性,除非您知道所有列名称。否则,您需要一个动态数据透视(谷歌:“mysql动态数据透视”)。对于数据库中的大多数用途,最好采用三列格式。

答案 3 :(得分:0)

您可以使用dplyr创建所有唯一对的列表,使用crossprod来计算一对类别共有的用户数。

> library(dplyr)
> data <- data %>% group_by(user_id, category) %>% summarize(records = sign(n()))
> crossprod(table(data$user_id, data$category))

    A B C
  A 4 1 4
  B 1 4 2
  C 4 2 5