簡體   English   中英

根據組和另一個數據幀刪除R數據幀中的行

[英]remove rows in R data frame based on group and another data frame

有兩個數據框

dat1 <- data.frame(group= c(11,11,12,12,13,13,14,14,15,15,16,16,17,17,17,18,18,18),name= c("A","B","C","D","E","F","G","H","I","J","A","B","E","F","W","A","B","V"))

dat2 <- data.frame(ID=c(1,1,2,2,3,3),name =c("A","B","E","F","X","Y"))

第二個數據幀具有按ID列分組的兩個值的組合。 並且基於第二數據幀(dat2),如果該特定組組合存在於dat2中 ,則需要刪除第一數據幀(dat1)中的行

例如:如果dat1中同時存在“ A”和“ B”,則應將其刪除。

因此,所需的輸出是

desiredat <- data.frame(group= c(12,12,13,13,15,15),name= c("C","D","G","H","I","J"))

尋找在R中達到相同目的的方法。

這樣的東西...?

dat1[dat1$name %in% setdiff(dat1$name, dat2$name), ]
3     12    C
4     12    D
7     14    G
8     14    H
9     15    I
10    15    J
15    17    W
18    18    V

這可以通過反聯接來解決。 但是,我們需要確定必須從dat1刪除哪個組ID group

library(data.table)
# count names per ID
setDT(dat2)[, n.id := .N, by = ID]
# identify groups to remove by joining and ... 
groups_to_remove <- dat2[setDT(dat1), on = "name", nomatch = 0L][
  # ... check which groups have a match with the complete set of names
  , which(n.id == .N), by = .(ID, group)]
# anti join
dat1[!groups_to_remove, on = "group"]
  group name 1: 12 C 2: 12 D 3: 14 G 4: 14 H 5: 15 I 6: 15 J 7: 19 A 8: 19 X 

刪除組19,因為名稱“ A”和“ X”在dat2屬於不同的ID。


更簡化的方法使用all()而不是計算唯一名稱:

library(data.table)
setDT(dat1)
setDT(dat2)
groups_to_remove <- dat1[dat2, on = "name"][, which(all(ID == ID[1])), by = group]
dat1[!groups_to_remove, on = "group"]
  group name 1: 12 C 2: 12 D 3: 14 G 4: 14 H 5: 15 I 6: 15 J 7: 19 A 8: 19 X 

與上面的dplyr語法相同:

library(dplyr)
dat2 %>% 
  left_join(dat1, by = "name") %>% 
  group_by(group) %>% 
  summarise(all_have_same_id = all(ID == ID[1L])) %>% 
  filter(all_have_same_id) %>% 
  anti_join(dat1, ., by = "group")
  group name 1 12 C 2 12 D 3 14 G 4 14 H 5 15 I 6 15 J 7 19 A 8 19 X Warning message: Column `name` joining factors with different levels, coercing to character vector 

數據

OP提供的樣本數據集dat1包含以下組:其中, dat2不包含任何名稱,或者所有名稱都在dat2一個ID中(可能加上一個附加名稱),但是缺少一個用例,其中ID中僅包含一個名稱的dat2 因此,我添加了這個用例(作為第19組):

dat1 <- data.frame(
  group= c(11,11,12,12,13,13,14,14,15,15,16,16,17,17,17,18,18,18,19,19),
  name= c("A","B","C","D","E","F","G","H","I","J","A","B","E","F","W","A","B","V","A","X"))

dat2 <- data.frame(ID=c(1,1,2,2,3,3),name =c("A","B","E","F","X","Y"))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM