【问题标题】:efficiently make an all-by-all co-incidence tibble from an incidence tibble有效地从一个入射小标题制作一个所有的所有重合小标题
【发布时间】:2021-06-22 14:41:36
【问题描述】:

我有一个小标题,可以编码哪些人喜欢哪些食物。有约 300 万行,约 92k 人,约 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))

我也尝试使用wider 包:

library(widyr)

pairwise_count(tbl = food_prefs, item = person, feature = food)

并遇到了:

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

【问题讨论】:

    标签: r tidyverse tidyr purrr tibble


    【解决方案1】:

    如果你只看实际一起出现的食物组合,它会更合适:

    food_prefs %>%
      inner_join(food_prefs, by = 'person') %>%
      filter(food.x < food.y) %>%
      count(food.x, food.y)
    
    # A tibble: 1,999,000 x 3
       food.x food.y     n
       <ord>  <ord>  <int>
     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
    # … with 1,998,990 more rows
    

    【讨论】:

      【解决方案2】:

      我认为最好的方法是使用稀疏矩阵而不是密集矩阵,例如Matrix 包。稀疏矩阵非常节省内存,它允许您计算邻接矩阵(食物的共现,或者如果您反转操作,则人的共现)。然后您可以将矩阵解构为成对列表。

      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多