2017-03-29 10 views
0

E型SKUまたは非E型SKUを持つデータセットがあります。私の目的は、どのような順序であっても、EタイプのSKUと同様の非EタイプのSKUを販売したかどうかを調べることです。特定の項目のグループ単位で行単位の重複を検索します。

たとえば、W123でE123を販売した場合、これは重複しているとみなされます。 E123を別のE123で販売した場合、これは重複しているとはみなされません。 W123をW123で販売した場合、重複しているとはみなされません。要約すると、少なくとも1つのEタイプSKUと少なくとも1つの非EタイプSKUを持つ複製を見つける必要があります。

私は尋ねた前の例ではSO(Find row-wise duplicates by groups)と同様であるが、その方法論でのチャレンジはsub("^E","", Product)が適用されたとき、私はもはや私がE型SKUまたはEでE型SKUを比較していますかどうかを知ることではありません非EタイプのSKUを備えたタイプのSKU。ここで

はサンプルデータです:

dput(Test_File) 
structure(list(Order = c(1, 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 
5, 5), Product = c("E12960", "E12960", "E12960", "W12960", "W12960", 
"W12960", "E1234", "E2345", "W2355", "A1235", "C-A-1234", "W-1234", 
"A-1234", "C-1234")), .Names = c("Order", "Product"), row.names = c(NA, 
14L), class = "data.frame") 

ここで予想されます出力:

dput(Output_File) 
structure(list(Order = c(1, 2, 3, 4, 5), Duplicate = c("N", "Y", 
"N", "N", "N")), .Names = c("Order", "Duplicate"), row.names = c(NA, 
5L), class = "data.frame") 

はここに私の作業コードです:

Test_File[,"ESKU_Present"]<-grepl("^E",Test_File$Product,ignore.case = TRUE) 

#Strip initial identifiers 
toMatch<-c("^E","^W","^A","^C-","^W-","C-A-","^A-") 
Test_File[grepl(paste(toMatch,collapse="|"),Test_File$Product,ignore.case = TRUE),"New_Product_ID"]<-sub(paste(toMatch,collapse="|"), "", Test_File$Product) 

Output <- Test_File %>% 
    dplyr::group_by(Order) %>% 
    #find those orders that have at least one ESKU and one non-ESKU 
    mutate(Duplicate = (any(ESKU_Present ==c("FALSE")) & any(ESKU_Present == c("TRUE")))) %>% 
    dplyr::filter(Duplicate == "TRUE") %>% 
    dplyr::summarise(Final_Flag = any(duplicated(New_Product_ID))) %>% 
    right_join(Test_File) %>% 
    dplyr::select(Order, Final_Flag) 

Output[is.na(Output$Final_Flag),"Final_Flag"]<-FALSE 
Output<-dplyr::distinct(Output) 

私は2つの質問があります。

をa)の方法私はを使用するのですか?私は何をしようとしているのですか? b)これを行うにはもっと速い方法がありますか?私は元のデータセット(これは約1M行あります)上に、上記のコードは永遠に取っているので、これを求めています。

答えて

1

data.tableでこれを行うことができます。 'data.frame'を 'data.table'(setDT(Test_File))に変換し、非数値( 'v1')と数値の部分文字列を抽出し、空白で置き換え、 'Order がuniqueの数字以外の文字の要素が1より大きく、数字の部分に重複する文字がある場合は、anyの非数字の文字が 'E'であるかどうかを確認します。

library(data.table) 
setDT(Test_File)[, { 
      v1 <- sub("\\d+", "", Product) 
      v2 <- sub("\\D+", "", Product) 
     .(Duplicate = any(v1=="E") & uniqueN(v1)>1 & anyDuplicated(v2)>0)} , Order] 
#  Order Duplicate 
#1:  1  FALSE 
#2:  2  TRUE 
#3:  3  FALSE 
#4:  4  FALSE 
#5:  5  FALSE 

注:これは、代わりに( '複製')などの論理列を維持する方が良いかもしれ 'Y/N'

+1

はありがとうございます。あなたは天才です - 私はちょうど2行で私に10行かかったのです。あなたがしたことを説明してもらえますか?私は 'data.table'にあまり慣れておらず、まだ学習中です。 – watchtower

+0

ありがとうございます。 'sub()'の中に式を書くのに良いリソースがありますか?私はいつもこれと闘う。私はちょうど '\\ d +'と '\\ D +'について学んだ... – watchtower

+1

@watchtower私はいくつかの説明を追加しました。あなたがそれ以上の説明が必要な場合は教えてください – akrun

関連する問題