【问题标题】:How to calculate common values across different groups?如何计算不同组的共同值?
【发布时间】:2018-12-13 20:24:43
【问题描述】:

我正在尝试使用 igraph 包创建用于创建网络图表的数据框。我有示例数据“mydata_data”,我想创建“expected_data”。

我可以轻松计算访问特定商店的客户数量,但是如何计算去商店 x1 和商店 x2 等的常见客户集合。

我有 500 多家商店,所以我不想手动创建列。下面给出了用于重现目的的示例数据:

mydata_data<-data.frame(
  Customer_Name=c("A","A","C","D","D","B"),
  Store_Name=c("x1","x2","x2","x2","x3","x1"))

expected_data<-data.frame(
 Store_Name=c("x1","x2","x3","x1_x2","x2_x3","x1_x3"), 
 Customers_Visited=c(2,3,1,1,1,0))

【问题讨论】:

  • 是否还应该有一行 x1_x2_x3 或者您一次只需要 2 个 Store_Name 的组合?
  • 一次只有 2 个商店 ...

标签: r dplyr igraph


【解决方案1】:

通过dplyr 的另一种可能的解决方案是为每个客户创建一个包含所有组合的列表,取消该列表,计数并与具有所有组合的数据框合并,即

library(tidyverse)

df %>%
    group_by(Customer_Name) %>%
    summarise(combos = list(unique(c(unique(Store_Name), paste(unique(Store_Name), collapse = '_'))))) %>%
    unnest() %>%
    group_by(combos) %>%
    count() %>%
    right_join(data.frame(combos = c(unique(df$Store_Name), combn(unique(df$Store_Name), 2, paste, collapse = '_'))))

给出,

# A tibble: 6 x 2
# Groups:   combos [?]
  combos     n
  <chr>  <int>
1 x1         2
2 x2         3
3 x3         1
4 x1_x2      1
5 x1_x3     NA
6 x2_x3      1

注意:确保您的 Store_Name 变量是字符 NOT 因素,否则 combn() 将失败

【讨论】:

    【解决方案2】:

    这是igraph 方法:

    A <- as.matrix(as_adj(graph_from_edgelist(as.matrix(mydata_data), directed = FALSE)))
    stores <- as.character(unique(mydata_data$Store_Name))
    storeCombs <- t(combn(stores, 2))
    
    data.frame(Store_Name = c(stores, apply(storeCombs, 1, paste, collapse = "_")),
               Customers_Visited = c(colSums(A)[stores], (A %*% A)[storeCombs]))
    #   Store_Name Customers_Visited
    # 1         x1                 2
    # 2         x2                 3
    # 3         x3                 1
    # 4      x1_x2                 1
    # 5      x1_x3                 0
    # 6      x2_x3                 1
    

    解释:A是对应无向图的邻接矩阵。 stores 简直就是

    stores
    # [1] "x1" "x2" "x3"
    

    同时

    storeCombs
    #      [,1] [,2]
    # [1,] "x1" "x2"
    # [2,] "x1" "x3"
    # [3,] "x2" "x3"
    

    接下来的主要技巧是如何获得Customers_Visited:前三个数字只是stores的邻居的对应数量,而我们从公共图邻居中得到的普通客户(我们从A)。

    【讨论】:

      【解决方案3】:

      这是获取数据的一种可能方式

      这里有一个辅助函数改编形式:Generate all combinations, of all lengths, in R, from a vector

      comball <- function(x) do.call("c", lapply(seq_along(x), function(i) combn(as.character(x), i, FUN = list)))
      

      然后你可以将它与一些整洁的诗歌功能一起使用

      library(dplyr)
      library(purrr)
      library(tidyr)
      
      mydata_data %>% 
        group_by(Customer_Name) %>% 
        summarize(visits = list(comball(Store_Name))) %>% 
        mutate(visits = map(visits, ~map_chr(., ~paste(., collapse="_")))) %>% 
        unnest(visits) %>% 
        count(visits)
      

      【讨论】:

        【解决方案4】:

        另一个选项,base R:

        获取所有可能的商店列表

        all_stores <- as.character(unique(mydata_data$Store_Name))
        

        找出 1 或 2 家商店的不同组合:

        all_comb_store <- lapply(1:2, function(n) combn(all_stores, n))
        

        对于每个合并的商店数量,获取访问过这两个商店的客户数量,然后将该值与商店名称组合在 data.frame 中:

        do.call(rbind, 
                lapply(all_comb_store, 
                       function(nb_comb) {
                         data.frame(Store_Name=if (nrow(nb_comb)==1) as.character(nb_comb) else apply(nb_comb, 2, paste, collapse="_"), 
                                    Customers_Visited=apply(nb_comb, 2, 
                                                            function(vec_stores) {
                                                               length(Reduce(intersect, 
                                                                      lapply(vec_stores, 
                                                                             function(store) mydata_data$Customer_Name[mydata_data$Store_Name %in% store])))}))}))
        #  Store_Name Customers_Visited
        #1         x1                 2
        #2         x2                 3
        #3         x3                 1
        #4      x1_x2                 1
        #5      x1_x3                 0
        #6      x2_x3                 1
        

        【讨论】:

          【解决方案5】:

          使用dplyr:自我加入,然后组成组并获得唯一计数。与考虑所有组合的其他答案相比,这应该快得多。

          注意:它不显示不存在的对。另外,这里x1_x1 的意思当然是x1

          left_join(mydata_data, mydata_data, by = "Customer_Name")  %>%
            transmute(Customer_Name,
                      grp = paste(pmin(Store_Name.x, Store_Name.y),
                                  pmax(Store_Name.x, Store_Name.y), sep = "_")) %>% 
            group_by(grp) %>% 
            summarise(n = n_distinct(Customer_Name))
          
          # # A tibble: 5 x 2
          #   grp       n
          #   <chr> <int>
          # 1 x1_x1     2
          # 2 x1_x2     1
          # 3 x2_x2     3
          # 4 x2_x3     1
          # 5 x3_x3     1
          

          数据无因素:

          mydata_data<-data.frame(
            Customer_Name=c("A","A","C","D","D","B"),
            Store_Name=c("x1","x2","x2","x2","x3","x1"),
            stringsAsFactors = FALSE)
          

          【讨论】:

            猜你喜欢
            • 2018-01-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-09-14
            相关资源
            最近更新 更多