【问题标题】:Finding Unique Users When Changing Info更改信息时查找唯一用户
【发布时间】:2021-07-01 17:20:16
【问题描述】:

我有以下数据:

dat <- data.frame(user_id = c(101,102,102,103,103,106),
           phone_number = c(4030201, 4030201, 4030202, 4030202, 4030203, 4030204))

我想计算唯一用户。如您所见,这里我们有 2 个唯一用户。所以,最终我要创建的表如下:

user_id    phone_number    new_user_id 
    101         4030201              1
    102         4030201              1  
    102         4030202              1
    103         4030202              1
    103         4030203              1
    106         4030204              2

关于如何在 R 中计算这个的任何想法?或者用不同的语言,然后我可以将代码翻译成 R。

【问题讨论】:

    标签: r igraph


    【解决方案1】:

    Updated02(需要做一些小的调整) 我不得不问两个问题才能解决它。如果您经常处理此类问题,则需要学习igraph 包,该包主要用于网络分析。也许有一种更简单的方法,但现在我认为它会做。让我们带您了解一下:

    library(dplyr)
    library(purrr)
    
    # In the firs chunk we iterate over every row of your data set to find out
    # whether there is a connection between the corresponding rows and the others
    
    map(1:nrow(dat), function(x) {
      dat %>%
        mutate(id = row_number()) %>%
        pmap_lgl(., ~ {x <- unlist(dat[x,]); 
        any(x %in% c(...))})
    }) %>%
      exec(cbind, !!!.) %>%
      as.data.frame() -> dat2
    
    dat2 %>%
      pmap(~ sub("V", "", names(dat2))[c(...)] %>% as.numeric()) -> ids
    
    [[1]]
    [1] 1 2
    
    [[2]]
    [1] 1 2 3
    
    [[3]]
    [1] 2 3 4
    
    [[4]]
    [1] 3 4 5
    
    [[5]]
    [1] 4 5 8
    
    [[6]]
    [1] 6
    
    [[7]]
    [1] 7
    
    [[8]]
    [1] 5 8
    

    然后我们将所有相关的ids 组合在一起。这部分我使用了我亲爱的朋友@det 和@Ian Campbell 提出的solutions,因为我不知道如何使用igraph

    library(igraph)
    
    map(ids, function(a) map_int(ids, ~length(base::intersect(a, .x)) > 0) * 1L) %>% 
      reduce(rbind) %>%
      graph.adjacency() %>%
      as.undirected() %>%
      components() %>%
      pluck("membership") %>%
      split(seq_along(.), .) %>%
      map(~unique(unlist(ids[.x]))) -> grouped_ids
    
    $`1`
    [1] 1 2 3 4 5 8
    
    $`2`
    [1] 6
    
    $`3`
    [1] 7
    

    在我们将所有相关的数据组合在一起之后,我们就可以对我们的数据集进行分组:

    dat %>%
      mutate(id = row_number()) %>%
      rowwise() %>%
      mutate(grp = seq(length(grouped_ids))[map_lgl(grouped_ids, ~ id %in% .x)])
    
      user_id phone_number id grp
    1     101      4030201  1   1
    2     102      4030201  2   1
    3     102      4030202  3   1
    4     103      4030202  4   1
    5     103      4030203  5   1
    6     106      4030204  6   2
    7     107      4030205  7   3
    8     111      4030203  8   1
    

    数据

    structure(list(user_id = c(101, 102, 102, 103, 103, 106, 107, 
    111), phone_number = c(4030201, 4030201, 4030202, 4030202, 4030203, 
    4030204, 4030205, 4030203)), class = "data.frame", row.names = c(NA, 
    -8L))
    

    【讨论】:

    • 如果我们将 user_id: 104 和 phone_number: 4030203 添加到我们的数据中,它不会检测到这个用户是相同的。此外,如果我们添加 user_id: 107 和 phone_number: 4030205,它不会将此用户检测为新用户。
    • 检查此数据 dat
    • 这太棒了,我真的应该研究一下。谢谢一百万!
    • 很清楚你用其他问题来解决这个问题。
    • 非常感谢亲爱的@IanCampbell。实际上这很有趣,因为我创建了所有边缘但不知道如何对它们进行分组,但显然正如我朋友的回答所示 graph.data.frame 也会从原始数据集创建它。它可能似乎有一些不必要的步骤,但我保持原样,以便每个人的贡献都是不同的并得到认可。
    【解决方案2】:

    稍微简化一下我朋友的answer

    dat <- data.frame(user_id = c(101,102,102,103,103,106),
                      phone_number = c(4030201, 4030201, 4030202, 4030202, 4030203, 4030204))
    
    library(tidyverse)
    library(igraph)
    
    graph.data.frame(dat) %>%
      components() %>%
      pluck(membership) %>%
      stack() %>%
      set_names(c('GRP', 'user_id')) %>%
      right_join(dat %>% mutate(user_id = as.factor(user_id)), by = c('user_id'))
    
      GRP user_id phone_number
    1   1     101      4030201
    2   1     102      4030201
    3   1     102      4030202
    4   1     103      4030202
    5   1     103      4030203
    6   2     106      4030204
    

    在 cmets 中给出的 dat 上,它给出了

      GRP user_id phone_number
    1   1     101      4030201
    2   1     102      4030201
    3   1     102      4030202
    4   1     103      4030202
    5   1     103      4030203
    6   2     106      4030204
    7   3     107      4030205
    8   1     111      4030203
    

    【讨论】:

      【解决方案3】:

      这是一个igraph 选项

      dat %>%
          mutate(new_user_id = membership(components(graph_from_data_frame(.)))[as.character(user_id)])
      

      给了

        user_id phone_number new_user_id
      1     101      4030201           1
      2     102      4030201           1
      3     102      4030202           1
      4     103      4030202           1
      5     103      4030203           1
      6     106      4030204           2
      

      【讨论】:

        猜你喜欢
        • 2021-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-15
        • 1970-01-01
        • 2013-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多