重复标识符 - 如何使用Tidyverse动态传播列中的重复值

时间:2017-11-06 22:09:28

标签: r tidyverse

library(tidyverse)  

这个问题的灵感来自Jake Kaupp对问题的回答 " tidyr / dplyr - 为重复的ID传播多个变量 " 。使用提供的样本数据(底部),我希望每行只有一个Id,但是有一些重复id的实例(148和188)。由于有不同的电话号码,我想动态地传播它们,以便每个号码都有一列。在我的真实数据集中,我不确定会有多少重复的ID,这将会不断变化。我想在Tidyverse内做所有这些,但我被困住了:

首先,我使用下面的代码查找所需的最大列数...

cols <-Df %>% 
group_by(Id) %>%
group_size() %>% 
max()

接下来,我想做类似下面代码的事情,但是&#34;分开_&#34;已弃用。我不知道在这里用什么?我尝试过使用tidyr :: spread进行各种尝试,并查看其他选项以解决重复的标识符,例如添加索引列(mutate(I = row_numbers()),但无法使其工作要么。

Df%>%
group_by(Id) %>%
separate_("Ph1", paste0("1:3", 1:cols), sep = ",", fill = "right") 

有一种简单的方法可以实现这一目标吗?动态方面很重要,因为数据集总会发生变化,最终我想将这部分作为一个函数。

示例数据:

Id<-c(199,148,148,145,177,165,144,121,188,188,188,111)
Ph1<-c(6532881717,6572231223,6541132112,6457886543,6548887777,7372222222,6451123425,6783450101,7890986543,6785554444,8764443344,6453348736)
Ph2<-c(NA,NA,NA,NA,NA,7372222222,NA,NA,NA,6785554444,NA,NA)

Df<-data.frame(Id,Ph1,Ph2)

1 个答案:

答案 0 :(得分:2)

您可以创建新列,为给定Id的每个电话号码分配唯一ID,然后使用该新列进行传播。这避免了重复的ID&#34;问题。在传播时,这种方法固有地增加了所需的列数,以容纳每个Id的所有唯一电话号码。例如,在下面的代码中,我称之为新列seq(对于&#34;序列&#34;):

library(tidyverse)

Df %>% 
  gather(key, value, -Id) %>%
  filter(!is.na(value)) %>% 
  select(-key) %>% 
  group_by(Id) %>% 
  filter(!duplicated(value)) %>% 
  mutate(seq=paste0("Phone_",1:n())) %>% 
  spread(seq, value)
     Id    Phone_1    Phone_2    Phone_3
1   111 6453348736         NA         NA
2   121 6783450101         NA         NA
3   144 6451123425         NA         NA
4   145 6457886543         NA         NA
5   148 6572231223 6541132112         NA
6   165 7372222222         NA         NA
7   177 6548887777         NA         NA
8   188 7890986543 6785554444 8764443344
9   199 6532881717         NA         NA