重复标识符 - 如何使用 Tidyverse 在列中动态传播重复值
Duplicate Identifiers - How to Dynamically Spread Repeating Values in a Column using Tidyverse
library(tidyverse)
这个问题的灵感来自 Jake Kaupp 对问题 "tidyr/dplyr - spreading multiple variables for duplicate ids" 的回答。使用提供的示例数据(底部),我希望每行只有一个 ID,但是有一些重复 ID 的实例(148 和 188)。由于有不同的 phone 数字,我想动态地展开这些数字,以便每个数字都有一列。在我的真实数据集中,我不确定会有多少重复的 ID,而且这会不断变化。我想在 Tidyverse 中完成所有这些,但我被卡住了:
首先,我使用下面的代码找到所需的最大列数...
cols <-Df %>%
group_by(Id) %>%
group_size() %>%
max()
接下来,我想执行类似下面代码的操作,但 "separate_" 已被弃用。我不确定在这里使用什么?我尝试了 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)
您可以创建一个新列,为给定 Id
的每个 phone 号码分配唯一 ID,然后使用该新列进行传播。这避免了 "duplicate id" 问题。传播时,这种方法固有地添加了所需数量的列,以容纳每个 Id
的所有唯一 phone 数字。例如,在下面的代码中,我将新列命名为 seq
(对于 "sequence"):
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
library(tidyverse)
这个问题的灵感来自 Jake Kaupp 对问题 "tidyr/dplyr - spreading multiple variables for duplicate ids" 的回答。使用提供的示例数据(底部),我希望每行只有一个 ID,但是有一些重复 ID 的实例(148 和 188)。由于有不同的 phone 数字,我想动态地展开这些数字,以便每个数字都有一列。在我的真实数据集中,我不确定会有多少重复的 ID,而且这会不断变化。我想在 Tidyverse 中完成所有这些,但我被卡住了:
首先,我使用下面的代码找到所需的最大列数...
cols <-Df %>%
group_by(Id) %>%
group_size() %>%
max()
接下来,我想执行类似下面代码的操作,但 "separate_" 已被弃用。我不确定在这里使用什么?我尝试了 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)
您可以创建一个新列,为给定 Id
的每个 phone 号码分配唯一 ID,然后使用该新列进行传播。这避免了 "duplicate id" 问题。传播时,这种方法固有地添加了所需数量的列,以容纳每个 Id
的所有唯一 phone 数字。例如,在下面的代码中,我将新列命名为 seq
(对于 "sequence"):
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