根据 R 中的查找 table 保留特定的重复项

keep specific duplicate based on lookup table in R

感谢任何可以帮助我解决这个问题的人。几天来,我一直试图弄清楚这一点,但没有运气。如果有解决方案,我深表歉意,但广泛的网络搜索没有帮助。

所以我有两个数据集 df 和 df2,df1 是我的数据集,其中我有伪重复项(如果我只考虑某些变量则重复),df2 是我的查找 table。

df <- data.frame(
  x = c("green", "green", "blue", "orange", "orange"),
  y = c("W12", "W12", "W12", "W11", "W12"),
  z = c(23, 54, 21, 16, 54)
  )
df2 <- data.frame(y=c("W12","W11"), z=c(54, 16))

所以,我们有:

> df
       x   y  z
1  green W12 23
2  green W12 54
3   blue W12 21
4 orange W11 16
5 orange W12 54

> df2
     y  z
 1 W12 54
 2 W11 16

我正在寻找一种方法,不仅可以根据 (x,y) 清除其中一个重复项,还可以根据查找中的 z 值告诉 R 保留哪个 table。所以在这里,保留记录 #2 但不是基于它在数据集中的位置(在我的真实日期中,z 的值有时大而其他时间小,具体取决于 y)。

我试过使用 !replicate() 但找不到指向引用 table 的方法,只能保留第一条记录(或最后一条).

df_dup<-df[c("x", "y")]
df[!duplicated(df_dup),]

我也尝试了一些类似

的方法
ddply(df,c("x", "y"), 
             function(v) {
               if (nrow(v)>1) v[which(c(df$y, df$z) %in% c(df2$y, df2$z)), ]
               if (nrow(v)==1) v
               }
               )
df %>% 
  group_by(x,y) %>% 
  filter(c(df$y,df$z) %in% c(df2$y,df2$z))

但是这里发生了一些奇怪的事情,%in% 不完全匹配对,而是 (y,z) 的任意组合。

我希望的输出是

 df
       x   y  z
2  green W12 54
3   blue W12 21
4 orange W11 16
5 orange W12 54

但是选择第 2 行不是因为它是最后一行,而是因为它匹配查找 table。在我较长的数据集中,要保留的行最终可能是第一行或第二行。

再次提前感谢任何能在 R 中找到方法执行此操作的人。最终,我将需要在一个巨大的数据集上执行此操作,并将多个变量作为分组变量,其中只有一个是其中的一部分查找 table.

一种方法如下:

  1. 查找 dfxy 的所有重复行。为此,我们使用 Sven Hohenstein's answer found here:

    dup.ind <- which(duplicated(df[,c("x","y")]) | duplicated(df[,c("x","y")], fromLast = TRUE))
    
  2. 我们还想在 result 中保留所有其他行(没有重复的行),所以我们使用 setdiff 来识别那些:

    other.ind <- setdiff(seq_len(nrow(df)), dup.ind)
    
  3. dup.ind 只保留 df 中的 z 值等于 df2 中匹配 [=16] 的值=] 值。在这里,df2$z[match(df$y[dup.ind], df2$y)]df2 中为每个 dup.ind:

    查找 z
    keep.ind <- dup.ind[df$z[dup.ind] == df2$z[match(df$y[dup.ind], df2$y)]]
    
  4. 使用 c(keep.ind,other.ind) 对原始 df 进行子集化。在这里,我们sort这些来保持原来的顺序(但那不是必须的):

    result <- df[sort(c(keep.ind, other.ind)),]
    

使用您的输入数据,result 是:

print(result)
##       x   y  z
##2  green W12 54
##3   blue W12 21
##4 orange W11 16
##5 orange W12 54

我可能会...

library(data.table)
setDT(df); setDT(df2)

ord = +is.na(df2[df, on=c("y", "z"), which=TRUE])
unique(df[ order(ord) ], by=c("x","y"))

        x   y  z
1:  green W12 54
2: orange W11 16
3: orange W12 54
4:   blue W12 21

这会优先考虑在 df2 中匹配的行;但是如果你想做相反的事情(就像在问题的早期版本中那样),只需在 ord 的定义中放置 - 而不是 +.


工作原理:

X[Y, on, which=TRUE] returns,对于 Y 的每一行,匹配的 X 的行。如果有多个匹配项,则全部返回(但在您的查找 table 中,没有理由重复)。如果没有匹配项,则返回缺失值。

+is.na(w) 其中 w 是行号向量 returns 我们可以排序的向量:

  • 1 如果 w 是缺失值
  • 0否则

unique(Y[order(ord)], by) 按我们的向量排序 Y,然后像往常一样删除重复项,保留每组的第一个观察值。您可以交替执行此步骤 Y[order(ord), .SD[1L], by]