从一个数据框的多列中查找不在另一个数据框的多列中的元素
Finding elements from multiple columns of one dataframe that are not in multiple columns of another
library(tidyverse)
我有两个名为 Df1 和 Df2 的数据帧(请参阅底部的示例代码)。我想在 Df1(来自所有列)中找到不在 Df2 中任何 phone 数字列中的 phone 数字。
首先,我重构了 Df1,使每行只有一个 Id。
Df1<-Df1 %>%
gather(key, value, -Id) %>%
filter(!is.na(value)) %>%
select(-key) %>%
group_by(Id) %>%
filter(!duplicated(value)) %>%
mutate(Phone=paste0("Phone_",1:n())) %>%
spread(Phone, value)
接下来,我重命名 Df2,然后使用联接仅查找 Df1 中存在于 Df2 中的 ID。
Df2<-Df2%>%set_names(c("Id","Ph1","Ph2"))
DfJoin<-left_join(Df2,Df1,by="Id")
这就是我卡住的地方。我想找到 Df1(Phone1 Phone2 和 Phone3)中所有不在 Df2(Ph1 和 Ph2)中的数字。以下是代码的一些想法。我尝试了这个想法的许多变体,但找不到实现我想要的方法。最终产品应该只是 table,任何 Df1 列中的 phone 数字以及相关 ID 不在任何 Df2 列中。我还想知道是否还有其他连接或设置操作可以更有效地实现此目的?
DfJoin<-DfJoin%>%mutate(New=if_else(! DfJoin[2:3] %in% DfJoin[4:6]),1,0)
DfJoin<-DfJoin%>%filter(! DfJoin[2:3] %in% DfJoin[2:4])
示例数据:
数据框 1:
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)
Df1<-data.frame(Id,Ph1,Ph2)
数据框 2:
Id2<-c(199,148,142,145,177,165,144,121,182,109,188,111)
Phone1<-c(6532881717,6572231223,6541132112,6457886543,6548887777,7372222222,6451123425,6783450101,7890986543,6785554400,8764443344,6453348736)
Phone2<-c(NA,NA,NA,NA,NA,7372222222,NA,NA,NA,6785554444,NA,NA)
Df2<-data.frame(Id2,Phone1,Phone2)
你试过了吗anti_join(a, b, by = "x1")
这基本上为您提供了 a 中不在 b 中的所有行
DfJoin <- anti_join(Df1, Df2, by = "Id")
使用上面的备忘单在 tidyverse 中进行数据操作
思考这个问题的一种方式:
- 对于每个身份证号码,您在
df1
中有一组 phone 个号码。
- 每个身份证号码在
df2
中有一组 phone 个号码。
- 您想在每个 ID 中找到
df1
和 df2
之间的 set difference。
您可以通过将基本 R 函数 setdiff()
映射到连接的数据框来实现。为此,您需要将数据框转换为列表列格式,其中每个 ID 的所有 phone 数字都作为列表出现在数据框的 "cell" 中。这很容易通过组合 group_by()
、summarize()
和 list()
.
来完成
# create example data
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)
df1 <- data.frame(Id, ph1, ph2)
Id2 <- c(199,148,142,145,177,165,144,121,182,109,188,111)
phone1 <- c(6532881717,6572231223,6541132112,6457886543,6548887777,7372222222,6451123425,6783450101,7890986543,6785554400,8764443344,6453348736)
phone2 <- c(NA,NA,NA,NA,NA,7372222222,NA,NA,NA,6785554444,NA,NA)
df2 <- data.frame(Id=Id2, phone1, phone2)
# convert the data to list-column format
df1.listcol <- df1 %>%
gather(col, phone, -Id) %>%
na.omit() %>%
group_by(Id) %>%
summarize(phone_list1 = list(phone))
df2.listcol <- df2 %>%
gather(col, phone, -Id) %>%
na.omit() %>%
group_by(Id) %>%
summarize(phone_list2 = list(phone))
看看这些数据框,确保您了解我们是如何重新格式化它们的。显然,我们可以通过将这个转换过程变成一个函数,然后分别在df1
和df2
上调用该函数来节省几行代码,但我这里没有这样做。
# join the two listcol dfs by Id, then map setdiff on the two columns
result <-
df1.listcol %>%
left_join(df2.listcol, by='Id') %>%
mutate(only_list_1 = map2(phone_list1, phone_list2, ~setdiff(.x, .y))) %>%
select(Id, only_list_1) %>%
unnest()
result
result
是
Id only_list_1
148 6541132112
188 7890986543
188 6785554444
library(tidyverse)
我有两个名为 Df1 和 Df2 的数据帧(请参阅底部的示例代码)。我想在 Df1(来自所有列)中找到不在 Df2 中任何 phone 数字列中的 phone 数字。
首先,我重构了 Df1,使每行只有一个 Id。
Df1<-Df1 %>%
gather(key, value, -Id) %>%
filter(!is.na(value)) %>%
select(-key) %>%
group_by(Id) %>%
filter(!duplicated(value)) %>%
mutate(Phone=paste0("Phone_",1:n())) %>%
spread(Phone, value)
接下来,我重命名 Df2,然后使用联接仅查找 Df1 中存在于 Df2 中的 ID。
Df2<-Df2%>%set_names(c("Id","Ph1","Ph2"))
DfJoin<-left_join(Df2,Df1,by="Id")
这就是我卡住的地方。我想找到 Df1(Phone1 Phone2 和 Phone3)中所有不在 Df2(Ph1 和 Ph2)中的数字。以下是代码的一些想法。我尝试了这个想法的许多变体,但找不到实现我想要的方法。最终产品应该只是 table,任何 Df1 列中的 phone 数字以及相关 ID 不在任何 Df2 列中。我还想知道是否还有其他连接或设置操作可以更有效地实现此目的?
DfJoin<-DfJoin%>%mutate(New=if_else(! DfJoin[2:3] %in% DfJoin[4:6]),1,0)
DfJoin<-DfJoin%>%filter(! DfJoin[2:3] %in% DfJoin[2:4])
示例数据:
数据框 1:
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)
Df1<-data.frame(Id,Ph1,Ph2)
数据框 2:
Id2<-c(199,148,142,145,177,165,144,121,182,109,188,111)
Phone1<-c(6532881717,6572231223,6541132112,6457886543,6548887777,7372222222,6451123425,6783450101,7890986543,6785554400,8764443344,6453348736)
Phone2<-c(NA,NA,NA,NA,NA,7372222222,NA,NA,NA,6785554444,NA,NA)
Df2<-data.frame(Id2,Phone1,Phone2)
你试过了吗anti_join(a, b, by = "x1")
这基本上为您提供了 a 中不在 b 中的所有行
DfJoin <- anti_join(Df1, Df2, by = "Id")
使用上面的备忘单在 tidyverse 中进行数据操作
思考这个问题的一种方式:
- 对于每个身份证号码,您在
df1
中有一组 phone 个号码。 - 每个身份证号码在
df2
中有一组 phone 个号码。 - 您想在每个 ID 中找到
df1
和df2
之间的 set difference。
您可以通过将基本 R 函数 setdiff()
映射到连接的数据框来实现。为此,您需要将数据框转换为列表列格式,其中每个 ID 的所有 phone 数字都作为列表出现在数据框的 "cell" 中。这很容易通过组合 group_by()
、summarize()
和 list()
.
# create example data
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)
df1 <- data.frame(Id, ph1, ph2)
Id2 <- c(199,148,142,145,177,165,144,121,182,109,188,111)
phone1 <- c(6532881717,6572231223,6541132112,6457886543,6548887777,7372222222,6451123425,6783450101,7890986543,6785554400,8764443344,6453348736)
phone2 <- c(NA,NA,NA,NA,NA,7372222222,NA,NA,NA,6785554444,NA,NA)
df2 <- data.frame(Id=Id2, phone1, phone2)
# convert the data to list-column format
df1.listcol <- df1 %>%
gather(col, phone, -Id) %>%
na.omit() %>%
group_by(Id) %>%
summarize(phone_list1 = list(phone))
df2.listcol <- df2 %>%
gather(col, phone, -Id) %>%
na.omit() %>%
group_by(Id) %>%
summarize(phone_list2 = list(phone))
看看这些数据框,确保您了解我们是如何重新格式化它们的。显然,我们可以通过将这个转换过程变成一个函数,然后分别在df1
和df2
上调用该函数来节省几行代码,但我这里没有这样做。
# join the two listcol dfs by Id, then map setdiff on the two columns
result <-
df1.listcol %>%
left_join(df2.listcol, by='Id') %>%
mutate(only_list_1 = map2(phone_list1, phone_list2, ~setdiff(.x, .y))) %>%
select(Id, only_list_1) %>%
unnest()
result
result
是
Id only_list_1
148 6541132112
188 7890986543
188 6785554444