From 330c433bca90c60f50084074af1de1d880841335 Mon Sep 17 00:00:00 2001 From: Patrik Schilter Date: Wed, 23 Jul 2025 00:14:51 +0200 Subject: [PATCH 1/2] Dyncov: Rename `predicted.CLV` -> `predicted.period.CLV` --- R/clv_template_controlflow_predict.R | 4 +++- R/f_generics_clvfittedtransactions.R | 6 ++++-- R/f_interface_predict_clvfittedtransactions.R | 3 ++- man/predict.clv.fitted.transactions.Rd | 3 ++- tests/testthat/helper_testthat_consistency.R | 5 ++++- tests/testthat/helper_testthat_inputchecks_nocov.R | 2 +- 6 files changed, 16 insertions(+), 7 deletions(-) diff --git a/R/clv_template_controlflow_predict.R b/R/clv_template_controlflow_predict.R index 03b9830d..cec24662 100644 --- a/R/clv_template_controlflow_predict.R +++ b/R/clv_template_controlflow_predict.R @@ -81,7 +81,9 @@ clv.controlflow.predict.add.uncertainty.estimates <- function(clv.fitted, dt.pre dt.boots[, Id := sub("_BOOTSTRAP_ID_[0-9]+$", "", Id)] # quantiles for each predicted quantity: select only the existing ones - cols.predictions <- c("PAlive", "CET", "DERT", "DECT", "predicted.mean.spending", "predicted.period.spending", "predicted.CLV") + cols.predictions <- c("PAlive", "CET", "DERT", "DECT", + "predicted.mean.spending", "predicted.period.spending", + "predicted.CLV", "predicted.period.CLV") cols.predictions <- cols.predictions[cols.predictions %in% colnames(dt.boots)] # Long-format for easier handling of different prediction columns diff --git a/R/f_generics_clvfittedtransactions.R b/R/f_generics_clvfittedtransactions.R index 92be7f00..c4eaf868 100644 --- a/R/f_generics_clvfittedtransactions.R +++ b/R/f_generics_clvfittedtransactions.R @@ -206,7 +206,7 @@ setMethod("clv.controlflow.predict.add.actuals", signature(clv.fitted="clv.fitte # .clv.controlflow.predict.post.process.prediction.table ------------------------------------------------------------------------------ setMethod("clv.controlflow.predict.post.process.prediction.table", signature = signature(clv.fitted="clv.fitted.transactions"), function(clv.fitted, dt.predictions, has.actuals, verbose, predict.spending, ...){ predicted.mean.spending <- i.predicted.mean.spending <- actual.period.spending <- i.actual.period.spending <- predicted.period.spending <- NULL - predicted.CLV <- CET <- DECT <- DERT <- NULL + predicted.CLV <- predicted.period.CLV <- CET <- DECT <- DERT <- NULL # Predict spending --------------------------------------------------------------------------------------- # depends on content of predict.spending: @@ -289,7 +289,7 @@ setMethod("clv.controlflow.predict.post.process.prediction.table", signature = s if("DERT" %in% colnames(dt.predictions)) dt.predictions[, predicted.CLV := DERT * predicted.mean.spending] if("DECT" %in% colnames(dt.predictions)) - dt.predictions[, predicted.CLV := DECT * predicted.mean.spending] + dt.predictions[, predicted.period.CLV := DECT * predicted.mean.spending] # If spending is predicted, also add predicted.period.spending dt.predictions[, predicted.period.spending := predicted.mean.spending * CET] @@ -316,6 +316,8 @@ setMethod("clv.controlflow.predict.post.process.prediction.table", signature = s if("predicted.CLV" %in% colnames(dt.predictions)) cols <- c(cols, "predicted.CLV") + if("predicted.period.CLV" %in% colnames(dt.predictions)) + cols <- c(cols, "predicted.period.CLV") setcolorder(dt.predictions, cols) diff --git a/R/f_interface_predict_clvfittedtransactions.R b/R/f_interface_predict_clvfittedtransactions.R index 63e6a2ab..46adc050 100644 --- a/R/f_interface_predict_clvfittedtransactions.R +++ b/R/f_interface_predict_clvfittedtransactions.R @@ -100,7 +100,8 @@ #' \item{actual.period.spending}{Actual total spending until prediction.end. Only if there is a holdout period and the prediction ends in it, otherwise not reported.} #' \item{predicted.mean.spending}{The mean spending per transactions as predicted by the spending model.} #' \item{predicted.period.spending}{The predicted total spending until prediction.end (\code{CET*predicted.mean.spending}).} -#' \item{predicted.CLV}{Customer Lifetime Value based on \code{DERT/DECT} and \code{predicted.mean.spending}.} +#' \item{predicted.CLV}{Customer Lifetime Value based on \code{DERT*predicted.mean.spending}.} +#' \item{predicted.period.CLV}{Customer Lifetime Value until prediction.end based on \code{DECT*predicted.mean.spending}.} #' #' If predicting for new customers (using \code{newcustomer()}), a numeric scalar indicating the expected #' number of transactions is returned instead. diff --git a/man/predict.clv.fitted.transactions.Rd b/man/predict.clv.fitted.transactions.Rd index e6a7c865..3595c22e 100644 --- a/man/predict.clv.fitted.transactions.Rd +++ b/man/predict.clv.fitted.transactions.Rd @@ -67,7 +67,8 @@ An object of class \code{data.table} with columns: \item{actual.period.spending}{Actual total spending until prediction.end. Only if there is a holdout period and the prediction ends in it, otherwise not reported.} \item{predicted.mean.spending}{The mean spending per transactions as predicted by the spending model.} \item{predicted.period.spending}{The predicted total spending until prediction.end (\code{CET*predicted.mean.spending}).} -\item{predicted.CLV}{Customer Lifetime Value based on \code{DERT/DECT} and \code{predicted.mean.spending}.} +\item{predicted.CLV}{Customer Lifetime Value based on \code{DERT*predicted.mean.spending}.} +\item{predicted.period.CLV}{Customer Lifetime Value until prediction.end based on \code{DECT*predicted.mean.spending}.} If predicting for new customers (using \code{newcustomer()}), a numeric scalar indicating the expected number of transactions is returned instead. diff --git a/tests/testthat/helper_testthat_consistency.R b/tests/testthat/helper_testthat_consistency.R index 535cb5d0..8df826cc 100644 --- a/tests/testthat/helper_testthat_consistency.R +++ b/tests/testthat/helper_testthat_consistency.R @@ -72,7 +72,10 @@ fct.testthat.consistency.cov.params.0.predict.same <- function(fitted.nocov, fit fct.compare.prediction.result <- function(dt.pred.nocov, dt.pred.cov){ if(is.dyncov == TRUE){ # DERT unequal to DECT because only predict short period! - expect_silent(data.table::setnames(dt.pred.cov, old="DECT",new = "DERT")) + expect_silent(data.table::setnames( + dt.pred.cov, + old=c("DECT", "predicted.CLV"), + new = c("DERT", "predicted.period.CLV"))) expect_true(isTRUE(all.equal(dt.pred.nocov[, !c("DERT", "predicted.CLV")], dt.pred.cov[, !c("DERT", "predicted.CLV")]))) }else{ diff --git a/tests/testthat/helper_testthat_inputchecks_nocov.R b/tests/testthat/helper_testthat_inputchecks_nocov.R index cf46402a..1278ba6a 100644 --- a/tests/testthat/helper_testthat_inputchecks_nocov.R +++ b/tests/testthat/helper_testthat_inputchecks_nocov.R @@ -215,7 +215,7 @@ fct.testthat.inputchecks.cannot.predict.without.spending <- function(method, is. regexp = "there is no spending data") # but works without spending expect_silent(dt.pred <- predict(clv.spending, newdata=clv.cdnow.nospending, predict.spending=FALSE, verbose=FALSE)) - expect_false(any(c("predicted.mean.spending","predicted.CLV") %in% colnames(dt.pred))) + expect_false(any(c("predicted.mean.spending","predicted.CLV", "predicted.period.CLV") %in% colnames(dt.pred))) } }) } From e09aa6361c239509b6cca860085136aa8cd4dab0 Mon Sep 17 00:00:00 2001 From: Patrik Schilter Date: Wed, 23 Jul 2025 14:50:17 +0200 Subject: [PATCH 2/2] Fix tests --- tests/testthat/helper_testthat_consistency.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/testthat/helper_testthat_consistency.R b/tests/testthat/helper_testthat_consistency.R index 8df826cc..38a69f33 100644 --- a/tests/testthat/helper_testthat_consistency.R +++ b/tests/testthat/helper_testthat_consistency.R @@ -74,8 +74,8 @@ fct.testthat.consistency.cov.params.0.predict.same <- function(fitted.nocov, fit # DERT unequal to DECT because only predict short period! expect_silent(data.table::setnames( dt.pred.cov, - old=c("DECT", "predicted.CLV"), - new = c("DERT", "predicted.period.CLV"))) + old=c("DECT", "predicted.period.CLV"), + new = c("DERT", "predicted.CLV"))) expect_true(isTRUE(all.equal(dt.pred.nocov[, !c("DERT", "predicted.CLV")], dt.pred.cov[, !c("DERT", "predicted.CLV")]))) }else{