The AutoRecommenderUpdate function is presented in this webpage. The reader will first see sample data in a format that is typically outputed from a product recommender algorithm. The data contains two distinct customers with ten different SKUs that they are most likely to purchase in ascending order, as well as the most recent timestamp in which the product recommender was ran. The source code of the AutoRecommenderFunction was then saved in order for it to be used to run tests that showed all three possible scenrios that the user will encounter as well as the different function paramaters that can be manipulated.
ProductRecommenderData = data.table :: data.table(CustomerID = rep(c(12346L,12347L),each = 10),
StockCode = c("23167","23165","22969","22501","22720","23154","22722",
"23298", "22961", "23293", "23245", "22961", "21977", "22952",
"22730","23240","22624","22950","47566","85123A"),
ProductRank = c(1:10), ModelTimeStamp = "2019-06-23 12:14:10")
ProductRecommenderData
## CustomerID StockCode ProductRank ModelTimeStamp
## 1: 12346 23167 1 2019-06-23 12:14:10
## 2: 12346 23165 2 2019-06-23 12:14:10
## 3: 12346 22969 3 2019-06-23 12:14:10
## 4: 12346 22501 4 2019-06-23 12:14:10
## 5: 12346 22720 5 2019-06-23 12:14:10
## 6: 12346 23154 6 2019-06-23 12:14:10
## 7: 12346 22722 7 2019-06-23 12:14:10
## 8: 12346 23298 8 2019-06-23 12:14:10
## 9: 12346 22961 9 2019-06-23 12:14:10
## 10: 12346 23293 10 2019-06-23 12:14:10
## 11: 12347 23245 1 2019-06-23 12:14:10
## 12: 12347 22961 2 2019-06-23 12:14:10
## 13: 12347 21977 3 2019-06-23 12:14:10
## 14: 12347 22952 4 2019-06-23 12:14:10
## 15: 12347 22730 5 2019-06-23 12:14:10
## 16: 12347 23240 6 2019-06-23 12:14:10
## 17: 12347 22624 7 2019-06-23 12:14:10
## 18: 12347 22950 8 2019-06-23 12:14:10
## 19: 12347 47566 9 2019-06-23 12:14:10
## 20: 12347 85123A 10 2019-06-23 12:14:10
AutoRecommenderUpdate <- function (
data,
FeaturedProduct,
ReplaceProduct = FALSE,
N = 10,
EntityColName = "CustomerID",
ProductColName = "StockCode",
Rank = "ProductRank",
TimeStamp = "ModelTimeStamp") {
# Ensure data is data.table----
if (!data.table::is.data.table(data)) {
data <- data.table::as.data.table(data)
}
# Gather Data to Determine Correct Scenerio----
CustomersWithFeaturedItem <- data[get(ProductColName) == FeaturedProduct, get(EntityColName)]
CustomersWithFeaturedItemTable <- data[get(EntityColName) %in% CustomersWithFeaturedItem]
CustomersWithoutFeaturedItemTable <- data[!(get(EntityColName) %in% CustomersWithFeaturedItem )]
# The Three Possible Scenerios are Listed Below----
# No Customer Has the Fetured Product Recommended to Them
# Every Customer Already Has the Fetured Product Recommended to Them
# Some Customers Have the Fetured Product Recommended to Them
if (nrow(CustomersWithFeaturedItemTable) == 0) {
A <- CustomersWithoutFeaturedItemTable
B <- NULL
} else if(nrow(CustomersWithoutFeaturedItemTable) == 0) {
return ("Every Customer has the featured product")
} else {
A <- CustomersWithoutFeaturedItemTable
B <- CustomersWithFeaturedItemTable
}
# Choose to replace the least likey product with the featured Product----
if(ReplaceProduct == TRUE) {
if(!N %in% unique(A[,get(Rank)])) {
stop("Rank does not exist in model")
}
data.table::set(
A,
i = A[get(Rank) == N, which = TRUE],
j = eval(ProductColName),
value = FeaturedProduct)
data <- data.table::rbindlist(
list(A,B),
fill = TRUE)
data.table::setorderv(
data,
cols = c(eval(EntityColName),
eval(Rank)))
return(data)
# Add the featured product to current recommendations----
} else {
# Test if timestamp should be added----
if(is.null(TimeStamp)){
DT <- data.table::data.table(
V1 = unique(A[,get(EntityColName)]),
V2 = FeaturedProduct,
V3 = 0)
data.table::setnames(
x = DT,
old = c("V1",
"V2",
"V3"),
new = c(eval(EntityColName),
eval(ProductColName),
eval(Rank)))
} else {
DT <- data.table::data.table(
V1 = unique(A[,get(EntityColName)]),
V2 = FeaturedProduct,
V3 = 0,
V4 = unique(A[,get(TimeStamp)]))
data.table::setnames(
x = DT,
old = c("V1",
"V2",
"V3",
"V4"),
new = c(eval(EntityColName),
eval(ProductColName),
eval(Rank),
eval(TimeStamp)))
}
# Finalize data prep and return----
data <- data.table::rbindlist(
list(DT,A,B),
fill = TRUE)
data.table::setorderv(
data,
cols = c(eval(EntityColName),
eval(Rank)))
return(data)
}
}
Test1 = AutoRecommenderUpdate(data = ProductRecommenderData , FeaturedProduct = "00")
Test1
## CustomerID StockCode ProductRank ModelTimeStamp
## 1: 12346 00 0 2019-06-23 12:14:10
## 2: 12346 23167 1 2019-06-23 12:14:10
## 3: 12346 23165 2 2019-06-23 12:14:10
## 4: 12346 22969 3 2019-06-23 12:14:10
## 5: 12346 22501 4 2019-06-23 12:14:10
## 6: 12346 22720 5 2019-06-23 12:14:10
## 7: 12346 23154 6 2019-06-23 12:14:10
## 8: 12346 22722 7 2019-06-23 12:14:10
## 9: 12346 23298 8 2019-06-23 12:14:10
## 10: 12346 22961 9 2019-06-23 12:14:10
## 11: 12346 23293 10 2019-06-23 12:14:10
## 12: 12347 00 0 2019-06-23 12:14:10
## 13: 12347 23245 1 2019-06-23 12:14:10
## 14: 12347 22961 2 2019-06-23 12:14:10
## 15: 12347 21977 3 2019-06-23 12:14:10
## 16: 12347 22952 4 2019-06-23 12:14:10
## 17: 12347 22730 5 2019-06-23 12:14:10
## 18: 12347 23240 6 2019-06-23 12:14:10
## 19: 12347 22624 7 2019-06-23 12:14:10
## 20: 12347 22950 8 2019-06-23 12:14:10
## 21: 12347 47566 9 2019-06-23 12:14:10
## 22: 12347 85123A 10 2019-06-23 12:14:10
## CustomerID StockCode ProductRank ModelTimeStamp
The featured item was successfully added to both customers.
Test2 = AutoRecommenderUpdate(data = Test1,FeaturedProduct = "00")
Test2
## [1] "Every Customer has the featured product"
We do not want to run this function if every customer already has the product recommended to them.
Test3 = AutoRecommenderUpdate(data = ProductRecommenderData ,FeaturedProduct = "23167")
Test3
## CustomerID StockCode ProductRank ModelTimeStamp
## 1: 12346 23167 1 2019-06-23 12:14:10
## 2: 12346 23165 2 2019-06-23 12:14:10
## 3: 12346 22969 3 2019-06-23 12:14:10
## 4: 12346 22501 4 2019-06-23 12:14:10
## 5: 12346 22720 5 2019-06-23 12:14:10
## 6: 12346 23154 6 2019-06-23 12:14:10
## 7: 12346 22722 7 2019-06-23 12:14:10
## 8: 12346 23298 8 2019-06-23 12:14:10
## 9: 12346 22961 9 2019-06-23 12:14:10
## 10: 12346 23293 10 2019-06-23 12:14:10
## 11: 12347 23167 0 2019-06-23 12:14:10
## 12: 12347 23245 1 2019-06-23 12:14:10
## 13: 12347 22961 2 2019-06-23 12:14:10
## 14: 12347 21977 3 2019-06-23 12:14:10
## 15: 12347 22952 4 2019-06-23 12:14:10
## 16: 12347 22730 5 2019-06-23 12:14:10
## 17: 12347 23240 6 2019-06-23 12:14:10
## 18: 12347 22624 7 2019-06-23 12:14:10
## 19: 12347 22950 8 2019-06-23 12:14:10
## 20: 12347 47566 9 2019-06-23 12:14:10
## 21: 12347 85123A 10 2019-06-23 12:14:10
## CustomerID StockCode ProductRank ModelTimeStamp
Notice that only the customer without the featured product got a new record. This avoids duplicate products being recommended to the same customer.
Test4 = AutoRecommenderUpdate(data = ProductRecommenderData,FeaturedProduct = "23167",ReplaceProduct = TRUE)
Test4
## CustomerID StockCode ProductRank ModelTimeStamp
## 1: 12346 23167 1 2019-06-23 12:14:10
## 2: 12346 23165 2 2019-06-23 12:14:10
## 3: 12346 22969 3 2019-06-23 12:14:10
## 4: 12346 22501 4 2019-06-23 12:14:10
## 5: 12346 22720 5 2019-06-23 12:14:10
## 6: 12346 23154 6 2019-06-23 12:14:10
## 7: 12346 22722 7 2019-06-23 12:14:10
## 8: 12346 23298 8 2019-06-23 12:14:10
## 9: 12346 22961 9 2019-06-23 12:14:10
## 10: 12346 23293 10 2019-06-23 12:14:10
## 11: 12347 23245 1 2019-06-23 12:14:10
## 12: 12347 22961 2 2019-06-23 12:14:10
## 13: 12347 21977 3 2019-06-23 12:14:10
## 14: 12347 22952 4 2019-06-23 12:14:10
## 15: 12347 22730 5 2019-06-23 12:14:10
## 16: 12347 23240 6 2019-06-23 12:14:10
## 17: 12347 22624 7 2019-06-23 12:14:10
## 18: 12347 22950 8 2019-06-23 12:14:10
## 19: 12347 47566 9 2019-06-23 12:14:10
## 20: 12347 23167 10 2019-06-23 12:14:10
You have the option to replace products of a perticular rank by sepcifying the N argument (I left it blank so N equals 10 by default). This can be useful if you are worried about overloading your servers with too many products or you want to control the amount of products you want to recommend to your customers.
Notice that the featured products will have a default product rank of 0 when you are not replacing an existing SKU. Hence, this will be the first product customer’s see and it facilitates deletion if needed.