options(scipen=10)
::p_load(latex2exp,Matrix,dplyr,tidyr,ggplot2,caTools,plotly)
pacmanrm(list=ls(all=TRUE))
load("data/tf4.rdata")
B$Buy
: Re-Purchase ProbabilityB$Rev
: Expected Revenue Contributionpar(mfrow=c(1,2), cex=0.8)
hist(B$Buy)
hist(log(B$Rev,10))
group_by(B,age) %>%
summarise(n=n(), Buy=mean(Buy), Rev=mean(Rev)) %>%
ggplot(aes(Buy,Rev,size=n,label=age)) +
geom_point(alpha=0.5,color='gold') +
geom_text(size=4) +
labs(title="Age Group Comparison (size: no. customers)") +
xlab("Buying Probability") + ylab("Expected Revenue") +
scale_size(range=c(4,20)) + theme_bw() -> p
ggplotly(p)
The \(Logistic\) function is handy
in defining parameterized S-curves
\[\Delta P(x|m,b,a) = m \cdot
Logis(\frac{10(x - b)}{a})\]
= function(x,m0,b0,a0) {m0*plogis((10/a0)*(x-b0))}
DP par(mar=c(4,4,2,1),cex=0.7)
curve(DP(x,m=0.20,b=30,a=40), 0, 60, lwd=2, ylim=c(0, 0.25),
main="F( x | m=0.2, b=30, a=40 )", ylab="delta P")
abline(h=seq(0,0.2,0.05),v=seq(0,60,5),col='lightgrey',lty=2)
The
m
: height of the s-curve (the max. effect)b
: center of the rising slopea
: width of the rising slopein one single program we can emulate all possible S-curves which
specifies how the effect (\(\Delta P\))
varies the
Now we can estimate the instrument’s
\[\hat{R}(x) = \left\{\begin{matrix} \Delta P \cdot M \cdot margin - x & , & P + \Delta P \leq 1\\ (1-P) \cdot M \cdot margin - x & , & else \end{matrix}\right.\]
Combining …
We can estimate
Note that both \(\Delta P\) and \(\hat{R}\) are functions of \(x\) given \(m,b,a\)
Estimating (Assuming) Raw Margin
# load(data/tf0.rdata)
# group_by(Z0, age) %>% summarise(sum(price)/sum(cost) - 1)
= 0.17 # assume margin = 0.17 margin
Estimating Expected Return
=0.2; b=25; a=40; x=30
m= pmin(1-B$Buy, DP(x,m,b,a))
dp = dp*B$Rev*margin - x
eR hist(eR,main="Dist. Expected Return",xlab="Expected Return",ylab="No. Customers")
Use the analysis above to answer the following questions …
🚴 How many customers should we apply this instruments
(eR > 0
)?
sum(eR > 0)
## [1] 7228
🚴 What is the expected return if we apply this instrument to ALL customers?
sum(eR)
## [1] -203881
🚴 What is the expected return if we only apply it to those who have positive return?
sum(eR[eR>0])
## [1] 75883.81
Assuming the instrument parameters (\(m,b,a\)), we can estimate how
eReturn
: expected return when applying to allN
: No. profitable caseseReturn2
: expected return when we only apply to the
profitablevary with the intensity of the instrument (eg. the face value of the coupon) in the simulation range of \(x \in [10, 45]\).
=0.2; b=25; a=40; X = seq(10,45,1)
m
= sapply(X, function(x) {
df = pmin(DP(x,m,b,a),1-B$Buy)
dp = dp*B$Rev*margin - x
eR c(x=x, eReturn=sum(eR), N=sum(eR > 0), eReturn2=sum(eR[eR > 0]))
%>% t %>% data.frame %>%
}) gather('key','value',-x)
%>% ggplot(aes(x=x, y=value, col=key)) +
df geom_hline(yintercept=0,linetype='dashed') +
geom_line(size=1.5,alpha=0.5) +
facet_wrap(~key,ncol=1,scales='free_y') + theme_bw()
With some modification of the code, we can define multiple (4) instruments at once
=c(0.20, 0.25, 0.15, 0.25)
mm=c( 25, 30, 15, 30)
bb=c( 40, 40, 30, 60)
aa= seq(0,60,2)
X do.call(rbind, lapply(1:length(mm), function(i) data.frame(
Inst=paste0('Inst',i), Cost=X,
Gain=DP(X,mm[i],bb[i],aa[i])
%>% data.frame %>%
))) ggplot(aes(x=Cost, y=Gain, col=Inst)) +
geom_line(size=1.5,alpha=0.5) + theme_bw() +
ggtitle("Prob. Function: f(x|m,b,a)")
and run simulation on multiple instrument to compare their cost effectiveness.
= seq(10, 60, 1)
X = do.call(rbind, lapply(1:length(mm), function(i) {
df sapply(X, function(x) {
= pmin(1-B$Buy, DP(x,mm[i],bb[i],aa[i]))
dp = dp*B$Rev*margin - x
eR c(i=i, x=x, eR.ALL=sum(eR), N=sum(eR>0), eR.SEL=sum(eR[eR > 0]) )
%>% t %>% data.frame
})
}))
%>%
df mutate_at(vars(eR.ALL, eR.SEL), function(y) round(y/1000)) %>%
gather('key','value',-i,-x) %>%
mutate(Instrument = paste0('I',i)) %>%
ggplot(aes(x=x, y=value, col=Instrument)) +
geom_hline(yintercept=0, linetype='dashed', col='blue') +
geom_line(size=1.5,alpha=0.5) +
xlab('Strength (x)') + ylab('Exp. Return($K)') +
ggtitle('Simulation: Cost Effectiveness of 4 Marketing Instruments') +
facet_wrap(~key,ncol=1,scales='free_y') + theme_bw() -> p
::ggplotly(p) plotly
With in df
we have the columns
i
: instrument idx
: unit costeR.ALL
: total expected payoff when apply to all
customersN
: the number of customers with positive expected net
payoffeR.SEL
: total expected payoff when only apply to the N
customersThe Optimal Strength for each instruments can be extracted simply by …
group_by(df, i) %>% top_n(1,eR.SEL)
## # A tibble: 4 x 5
## # Groups: i [4]
## i x eR.ALL N eR.SEL
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 34 -217614. 7569 93549.
## 2 2 40 -196943. 8783 143043.
## 3 3 22 -50497. 10880 107149.
## 4 4 43 -307871. 6979 106687.
Here is the number of customers in each age group.
par(cex=0.7, mar=c(2,2,1,2))
table(B$age) %>% barplot
🚴 Group Assignment:
If the 4
parameter combinations above each represents the effect of an instrument
to an age group:
■ I1 : a24, a29
■
I2 : a34, a39
■ I3 : a44, a49
■
I4 : a54, a59, a64, a69
Please find the optimal
strategy for each age group in terms of:
■ No. customers to apply
(N
)?
■ The strength of instrument
(x
)?
■ The expected return
(eR.SEL
)?
= seq(10, 60, 1)
X
= list(
agrp c("a24","a29"),
c("a34","a39"),
c("a44","a49"),
c("a54","a59","a64","a69")
)
= do.call(rbind, lapply(1:length(agrp), function(i) {
df = filter(B, age %in% agrp[[i]] )
ag sapply(X, function(x) {
= pmin(1- ag$Buy , DP(x,mm[i],bb[i],aa[i]))
dp = dp* ag$Rev *margin - x
eR c(i=i, x=x, eR.ALL=sum(eR), N=sum(eR>0), eR.SEL=sum(eR[eR > 0]) )
%>% t %>% data.frame
})
}))
group_by(df, i) %>% top_n(1,eR.SEL)
## # A tibble: 4 x 5
## # Groups: i [4]
## i x eR.ALL N eR.SEL
## <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 1 34 -52796. 626 5923.
## 2 2 40 -35113. 4175 70408.
## 3 3 22 -68.9 3472 36733.
## 4 4 42 -83643. 673 8012.