更改信息时如何查找独特的用户

4

我有以下数据:

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。
3个回答

4

更新02(需要进行一些微调) 我不得不提出两个问题才能解决它。如果您经常处理此类问题,则需要学习主要用于网络分析的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

接下来,我们将所有相关的id分组。在这一部分中,我使用了我的朋友@det和@Ian Campbell提出的解决方案,因为我不知道如何使用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))

1
如果我们将user_id:104和phone_number:4030203添加到我们的数据中,它不会将此用户识别为相同的用户。另外,如果我们添加user_id:107和phone_number:4030205,则不会将此用户识别为新用户。 - James Harrington
2
检查这些数据 dat <- data.frame(user_id = c(101,102,102,103,103,106,107,111), phone_number = c(4030201, 4030201, 4030202, 4030202, 4030203, 4030204, 4030205, 4030203)) - James Harrington
1
这太棒了,我真的应该好好学习一下。非常感谢! - James Harrington
1
很棒,你使用了其他问题来解决这个问题。 - Ian Campbell
1
非常感谢亲爱的@IanCampbell。实际上很有趣,因为我创建了所有的边缘,但不知道如何对它们进行分组,但是显然,正如我的朋友的答案所示,graph.data.frame也可以从原始数据集中创建它。这可能看起来有些不必要的步骤,但我保留它,以便每个人的贡献都是独特和受到认可的。 - Anoushiravan R
显示剩余5条评论

4

简化我朋友的答案

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

在评论中提供了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

1
这里是一个 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接