2017-03-29 1 views
0

E- 유형 SKU 또는 비 E- 유형 SKU가있는 데이터 세트가 있습니다. 내 목표는 어떤 순서로든 내가 E 타입 SKU와 유사한 E 타입 SKU를 판매했는지 여부를 찾는 것입니다.특정 항목에 대해 그룹별로 행별로 중복 찾기

예를 들어, W123으로 E123을 판매 한 경우 이는 중복으로 간주됩니다. E123을 다른 E123과 함께 판매 한 경우 이는 중복으로 간주되지 않습니다. 1223 원으로 123 위를 팔면 중복도되지 않을 것입니다. 요약하면 적어도 하나의 E- 유형 SKU와 하나 이상의 비 E- 유형 SKU가있는 복제본을 찾아야합니다.

내가 있슴 위의 예는 SO (Find row-wise duplicates by groups)과 비슷하지만 그 방법론 도전은 sub("^E","", Product)이 적용될 때, 나는 더 이상 내가 E 형 SKU 또는 E와 함께 E 형 SKU를 비교하고 있는지 알고 없다 유형 SKU가 아닌 E 유형 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) 

나는 두 가지 질문이 있습니다

을 ㄱ) 내가를 사용합니까?나는 무엇을하려고합니까? b) 더 빠른 방법이 있습니까? 나는 원래의 데이터 세트에 약 1M 행을 가지고 있기 때문에 위의 코드는 영원히 필요하기 때문에 이것을 묻습니다.

답변

1

data.table에서이를 수행 할 수 있습니다. 'data.frame'을 'data.table'(setDT(Test_File))로 변환하고 숫자가 아닌 문자를 일치시키고 공백으로 대체 한 다음 비 순차적 인 ('v1') 및 숫자 하위 문자열을 추출한 다음 'Order '이 unique 인 숫자가 아닌 문자에 대해 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

감사합니다. 당신은 천재입니다 - 당신은 단지 두 줄에 10 줄을 가져갔습니다. 당신이 한 일을 설명해 주시겠습니까? 나는'data.table'에 너무 익숙하지 않고 아직도 배우고있다. – watchtower

+0

고맙다. 'sub()'에 표현식을 작성하기위한 훌륭한 자료를 알고 있습니까? 나는 항상 이것으로 고투한다. 방금'\\ d +'와'\\ D +'에 대해 배웠습니다 ... – watchtower

+1

@watchtower 몇 가지 설명을 추가했습니다. 더 자세한 설명이 필요하면 알려주세요. – akrun

관련 문제