【问题标题】:remove rows in R data frame based on group and another data frame根据组和另一个数据框删除 R 数据框中的行
【发布时间】:2019-02-04 11:39:24
【问题描述】:

有两个数据框

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) 中的行。

例如:如果“A”和“B”存在于 dat1 中,则应将其删除。

因此,期望的输出是

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

在 R 中寻找实现相同目标的方法。

【问题讨论】:

  • 检查你的desiredat 我认为有一些值遗漏了

标签: r dataframe


【解决方案1】:

这可以通过反连接来解决。但是,我们需要确定哪些组 ID group 必须从 dat1 中删除。

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 的 ID 中仅包含一个名称。因此,我添加了这个用例(作为第 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"))

【讨论】:

    【解决方案2】:

    像这样...?

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-22
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多