2016-09-23 113 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