我有一个具有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行,上面的代码将永远存在。
答案 0 :(得分:1)
我们可以在data.table
中执行此操作。将'data.frame'转换为'data.table'(setDT(Test_File)
),通过匹配数字和非数字字符并用空格替换它来提取非数字('v1')和数字子字符串,然后按“订单”分组,我们检查是否有any
非数字字符是'E',而length
的{{1}}元素是非数字字符是否大于1并且数字部分有任何重复的字符。
unique
注意:最好保留逻辑列('重复')而不是'Y / N'