按组查找特定项

时间:2017-03-29 16:52:07

标签: r data.table dplyr

我有一个具有E-type SKU或非E-type SKU的数据集。我的目标是找出我是否以任何顺序销售E型SKU以及类似的非E型SKU。

例如,如果我用W123出售E123,这将被视为重复。如果我用另外的E123卖E123,这不会被认为是重复的。如果我用W123出售W123,它也不会被视为重复。总而言之,我需要找到一个至少有一个E型SKU和至少一个非E型SKU的副本。

我在SO上提到的前一个示例是类似的(Find row-wise duplicates by groups),但该方法的挑战是当应用sub("^E","", Product)时,我不再知道我是否正在比较E型SKU E型SKU或带E型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)

我有两个问题:

a)如何使用data.table来做我想做的事情? b)有没有更快的方法呢?我问这个是因为在我的原始数据集上有大约1M行,上面的代码将永远存在。

1 个答案:

答案 0 :(得分:1)

我们可以在data.table中执行此操作。将'data.frame'转换为'data.table'(setDT(Test_File)),通过匹配数字和非数字字符并用空格替换它来提取非数字('v1')和数字子字符串,然后按“订单”分组,我们检查是否有any非数字字符是'E',而length的{​​{1}}元素是非数字字符是否大于1并且数字部分有任何重复的字符。

unique

注意:最好保留逻辑列('重复')而不是'Y / N'