微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在更改信息时寻找唯一用户

如何解决在更改信息时寻找唯一用户

我有以下数据:

dat <- data.frame(user_id = c(101,102,103,106),phone_number = c(4030201,4030201,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。

解决方法

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

然后我们将所有相关的 id 组合在一起。这部分我使用了我亲爱的朋友@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,103,106,107,111),phone_number = c(4030201,4030201,4030202,4030203,4030204,4030205,4030203)),class = "data.frame",row.names = c(NA,-8L))
,

稍微简化我朋友的answer

dat <- data.frame(user_id = c(101,106),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
,

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。