The functions in the foretell package are fairly simple calls to the R optim
function with some data management in between. So in R if you run library(foretell);BdW
you can see the function definition.
In python, you would just rewrite the R optim call using scipy minimize. Here is a brief example of minimizing the same example in the foretell docs for the BdW
model:
from scipy.optimize import minimize
from scipy.special import beta
import numpy as np
surv = np.array([100,86.9,74.3,65.3,59.3])
h = 6
t = len(surv)
die = np.diff(-surv)
i = np.arange(0,t)
def dbw_ll(x):
a,b,c = x
s = beta(a,b + i**c)/beta(a,b)
p = np.diff(-s)
ll_ = die * np.log(p)
ll = ll_.sum() + surv[-1]*np.log(s[-1])
return -ll
bnds = [(0.001,10000)]*3
res = minimize(dbw_ll, x0=[1,1,1],
method='L-BFGS-B',
bounds=bnds)
print(res.x)
# R results 0.2593549 1.7226948 1.5842688
# agrees for 3 decimals
# projecting out
a, b, c = res.x
k = np.arange(0,t+h)
dbw = (beta(a,b+k**c)/beta(a,b))*100
fitted = dbw[0:t]
projected = dbw[t:]
It is mostly the same exercise for the other functions (mapping R functions to python). You just need to do a days worth of work to wrap these up in nice functions in python to replicate the same functionality in the R foretell library. (Did this example while waiting for a few queries to finish!)