R 有效地将所有共关联从关联TIBLE转换为关联TIBLE

R 有效地将所有共关联从关联TIBLE转换为关联TIBLE,r,tidyverse,tidyr,purrr,tibble,R,Tidyverse,Tidyr,Purrr,Tibble,我有一个TIBLE,它编码哪些人喜欢哪些食物。有约300万排,约9200人,约2k种食物。我计算了每种食物的受欢迎程度(有多少%的人喜欢它)。由此我计算出每一种食物的受欢迎程度(喜欢食物的概率是喜欢食物的概率的1倍,喜欢食物的概率是喜欢食物的概率的2倍)。现在我想计算每一种食物的受欢迎程度,但我已经尝试了几种方法,每次Rstudio都会崩溃。所以,我认为我需要找到一种更有效的方法(也许是从记忆的角度)来做这件事。我是这样做的。很抱歉,代码太多了,但我不认为有任何不必要的步骤,我已经尝试使用好的名

我有一个TIBLE,它编码哪些人喜欢哪些食物。有约300万排,约9200人,约2k种食物。我计算了每种食物的受欢迎程度(有多少%的人喜欢它)。由此我计算出每一种食物的受欢迎程度(喜欢食物的概率是喜欢食物的概率的1倍,喜欢食物的概率是喜欢食物的概率的2倍)。现在我想计算每一种食物的受欢迎程度,但我已经尝试了几种方法,每次Rstudio都会崩溃。所以,我认为我需要找到一种更有效的方法(也许是从记忆的角度)来做这件事。我是这样做的。很抱歉,代码太多了,但我不认为有任何不必要的步骤,我已经尝试使用好的名称,这样就可以清楚地知道每一位的作用

library(tidyverse)
lu <- compose(length, unique)

set.seed(37212)

num_people <- 92000
num_foods <- 2000
num_prefs <- 3e6

person <- sample(x = num_people, size = num_prefs, replace = TRUE)
food <- sample(x = num_foods, size = num_prefs, replace = TRUE)

tibble(person = factor(person, ordered = TRUE),
       food = factor(food, ordered = TRUE)) %>% 
    distinct() ->
    food_prefs

stopifnot(lu(food_prefs$person) == num_people)
stopifnot(lu(food_prefs$food) == num_foods)

food_prefs %>%
    group_by(food) %>%
    summarise(p = n()/num_people) %>%
    print() ->
    food_popularities

food_popularities %>% 
    mutate(food1 = food,
           food2 = food) %>% 
    expand(food1, food2) %>% 
    filter(food1 < food2) %>%
    print() ->
    food_pairs
    
food_pairs %>% 
    inner_join(food_popularities, 
               by = c('food1' = 'food')) %>% 
    inner_join(food_popularities, 
               by = c('food2' = 'food'),
               suffix = c('1', '2')) %>% 
    mutate(p_joint = p1*p2) %>% 
    print() ->
    pairwise_popularity_expected

food_prefs %>% 
    group_by(food) %>% 
    summarise(person_list = list(person)) %>% 
    print() ->
    food_liker_lists


# the line here that starts with 'mutate' is what crashes my computer

food_pairs %>% 
    inner_join(food_liker_lists, 
               by = c('food1' = 'food')) %>% 
    inner_join(food_liker_lists, 
               by = c('food2' = 'food'),
               suffix = c('1', '2')) %>% 
    mutate(joint_list = map2(person_list1, 
                             person_list2, 
                             intersect),
           num_joint = map_int(joint_list, length))
并会见了:

m%*%t(m)中的错误:
Cholmod错误“问题太大”,位于文件../MatrixOps/Cholmod_ssmult.c,第222行

我认为最好使用稀疏矩阵而不是密集矩阵,例如
矩阵
包。稀疏矩阵是非常高效的内存,它允许您计算邻接矩阵(如果您反向操作,则食物或人的共存)。然后你可以把矩阵分解成一个成对的列表

A <- spMatrix(ncol = length(unique(food_prefs$person)),
              nrow = length(unique(food_prefs$food)),
              j = as.numeric(factor(food_prefs$person)),
              i = as.numeric(factor(food_prefs$food)),
              x = rep(1, nrow(food_prefs)))
rownames(A) <- levels(factor(food_prefs$food))
colnames(A) <- levels(factor(food_prefs$person))

adj <- A %*% t(A)
food_pairs <- data.frame(food1=rownames(adj)[row(adj)],food2=colnames(adj)[col(adj)],num_joint=as.numeric(adj))
food_pairs <- food_pairs[food_pairs$food1 != food_pairs$food2, ]
head(food_pairs)
# food1 food2 num_joint
# 2   F10    F1        23
# 3  F100    F1        26
# 4 F1000    F1        25
# 5 F1001    F1        19
# 6 F1002    F1        27
# 7 F1003    F1        34

A我认为最好使用稀疏矩阵而不是密集矩阵,例如
矩阵
包。稀疏矩阵是非常高效的内存,它允许您计算邻接矩阵(如果您反向操作,则食物或人的共存)。然后你可以把矩阵分解成一个成对的列表

A <- spMatrix(ncol = length(unique(food_prefs$person)),
              nrow = length(unique(food_prefs$food)),
              j = as.numeric(factor(food_prefs$person)),
              i = as.numeric(factor(food_prefs$food)),
              x = rep(1, nrow(food_prefs)))
rownames(A) <- levels(factor(food_prefs$food))
colnames(A) <- levels(factor(food_prefs$person))

adj <- A %*% t(A)
food_pairs <- data.frame(food1=rownames(adj)[row(adj)],food2=colnames(adj)[col(adj)],num_joint=as.numeric(adj))
food_pairs <- food_pairs[food_pairs$food1 != food_pairs$food2, ]
head(food_pairs)
# food1 food2 num_joint
# 2   F10    F1        23
# 3  F100    F1        26
# 4 F1000    F1        25
# 5 F1001    F1        19
# 6 F1002    F1        27
# 7 F1003    F1        34

A如果你只看实际上同时出现的食物组合,它更适合:

food_prefs %>%
  inner_join(food_prefs, by = 'person') %>%
  filter(food.x < food.y) %>%
  count(food.x, food.y)
food\u prefs%>%
内部联接(食物优先,由='人')%>%
过滤器(食品x<食品y)%>%
计数(食物x,食物y)
#tible:1999000 x 3
食物
1 1      2         19
2 1      3         21
3 1      4         19
4 1      5         22
5 1      6         13
6 1      7         21
7 1      8         20
8 1      9         22
9 1      10        23
10 1      11        21
#…还有1998990行

如果你只看实际同时出现的食物组合,它更适合:

food_prefs %>%
  inner_join(food_prefs, by = 'person') %>%
  filter(food.x < food.y) %>%
  count(food.x, food.y)
food\u prefs%>%
内部联接(食物优先,由='人')%>%
过滤器(食品x<食品y)%>%
计数(食物x,食物y)
#tible:1999000 x 3
食物
1 1      2         19
2 1      3         21
3 1      4         19
4 1      5         22
5 1      6         13
6 1      7         21
7 1      8         20
8 1      9         22
9 1      10        23
10 1      11        21
#…还有1998990行