2016-09-23 112 views
3

谢谢任何​​能够帮助我的人。我试图解决这个问题,好几天没有运气。我很抱歉,如果解决方案在那里,但广泛的网络搜索没有帮助。根据R中的查找表保留特定的副本

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

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)的副本之一,但要能告诉R,它保持查找表中z的值。因此,在这里,保留记录#2,但不是基于它在数据集中的位置(在我的真实日期中,z的值有时很大,其他时间很小,取决于y)。

我尝试过使用!replicate()但找不到指向参考表的方法,只是为了保留第一个记录(或最后一个)。

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)) 

但一些时髦这里发生的一切东西线,并在%的%不匹配完全对,但的(Y,Z的任意组合)。

我希望的输出是

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

但随着行#2没有选择,因为它是最后一排,而是因为它的查找表匹配。在我较长的数据集中,要保留的行最终可能是第一个或第二个。

再次感谢所有能够在R中找到方法的人。最后,我需要在一个庞大的数据集上进行此操作,并将多个变量作为分组变量,其中只有一个变量是其中一个变量的一部分查找表。

+0

如果您基于df2中的内容保留它,这听起来很像保持54行的行(因为它出现在df2上)。你可以通过显示你想要的输出来使它更清晰。 – Frank

+0

是的,请添加您期望的输出,使其更易于理解。当我不得不在多个列中找到唯一值时,我使用的一个技巧是创建一个连接了值的单个列并对其进行比较。 –

+0

弗兰克,我很抱歉,是的,我想保持行#2。当我发布代码时,我终于改变了顺序。 –

回答

2

我可以做...

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]回报,为Y每行的X行(S),其是匹配的。如果有多个匹配项,它们都会被返回(但在查找表中,没有理由重复)。如果不匹配,则返回缺失值。

+is.na(w)其中w是行号的矢量返回一个载体,我们可以排序:

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

unique(Y[order(ord)], by)各种Y我们矢量,然后像往常一样丢弃重复,保持每组的第一次观察。此步骤可以交替使用Y[order(ord), .SD[1L], by]

+1

谢谢弗兰克!它工作得很好!我在另一个虚拟记录上尝试了一些更复杂的代码,然后让它翻录我的1M记录数据集,并且完美地完成了它的工作。再次谢谢你。 –

0

一种方法如下:

  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仅保留那些中的z值等于df2中匹配的y值的值。在这里,df2$z[match(df$y[dup.ind], df2$y)]查找在df2每个dup.indz值:

    keep.ind <- dup.ind[df$z[dup.ind] == df2$z[match(df$y[dup.ind], df2$y)]] 
    
  4. 子集原df使用c(keep.ind,other.ind)。在这里,我们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