Dear Alteryx Community,
I am hoping to find here someone who is knowledgeable in both Python and Alteryx.
In order to complete a workflow in Alteryx I require a Croston forecasting model for sporadic demand. I found that this was available in Python so I embedded it in my workflow. I am taking demand over 36 months (attached). I am then attempting to run the following forecasting model:
# List all non-standard packages to be imported by your
# script here (only missing packages will be installed)
from ayx import Package
#Package.installPackages(['pandas','numpy'])
import numpy as np
import sys
import random
import matplotlib.pyplot as plt
import pandas as pd
from ayx import Alteryx
ts = Alteryx.read("#1")
def Croston(ts,extra_periods=6,alpha=0.3):
d = np.array(ts) # Transform the input into a numpy array
col = len(d) # Historical period length
d = np.append(d,[np.nan]*extra_periods) # Append np.nan into the demand array to cover future periods
#level (a), periodicity(p) and forecast (f)
a,p,f = np.full((3,cols+extra_periods),np.nan)
q = 1 #periods since last demand observation
# Initialization
first_occurence = np.argmax(d[:cols]>0)
a[0] = d[first_occurence]
p[0] = 1 + first_occurence
f[0] = a[0]/p[0]
# Create all the t+1 forecasts
for t in range(0,cols):
if d[t] > 0:
a[t+1] = alpha*d[t] + (1-alpha)*a[t]
p[t+1] = alpha*q + (1-alpha)*p[t]
f[t+1] = a[t+1]/p[t+1]
q = 1
else:
a[t+1] = a[t]
p[t+1] = p[t]
f[t+1] = f[t]
q += 1
# Future Forecast
a[cols+1:cols+extra_periods] = a[cols]
p[cols+1:cols+extra_periods] = p[cols]
f[cols+1:cols+extra_periods] = f[cols]
df = pd.DataFrame.from_dict({"Demand":d,"Forecast":f,"Period":p,"Level":a,"Error":d-f})
Alteryx.write(df,1)
However, the model returns the error that 'df' is not defined:
---------------------- NameError Traceback (most recent call last) <ipython-input-2-7c889ddf879c> in <module> 35 36 df = pd.DataFrame.from_dict({"Demand":d,"Forecast":f,"Period":p,"Level":a,"Error":d-f}) ---> 37 Alteryx.write(df,1) NameError: name 'df' is not defined
If I indent line 37 I get no output.
Any assistance you could offer would be greatly appreciated.
Thank you,
Daniel
Solved! Go to Solution.
Hello @danielrg ,
The python code you have in place is erroneous. I did not look at the logic but rather the structure.
You are defining a function and not calling it anywhere. You need to pay attention to your indentation. It is basically the scope of your code.
basically df is out of scope when writing out your output.
I have made the code run but not sure about the output required and the logic you desire.
Now that it runs, you can debug it and make it fit your needs.
I hope you find it helpful.
Hi @danielrg
Among all the major concern is you are not calling function Croston any where.
Maybe adding it before write would work.
Croston()
Alteryx.write(df,1)
Just looking by the surface level
Hope this helps 🙂
Its advisable to look into @ImadZidan 's feedback too.
yes @atcodedog05 , you are right.
@danielrg , I would start with @atcodedog05 suggestion . you may still get an error as the dimension in your conversion to dataframe is not consistent.
Thank you both to @ImadZidan and @atcodedog05 . In fact both of you are correct. I combined both of your answers and arrived at the following working function:
from ayx import Alteryx
def Croston(ts,extra_periods=6,alpha=0.3):
d = np.array(ts) # Transform the input into a numpy array
cols = len(d) # Historical period length
d = np.append(d,[np.nan]*extra_periods) # Append np.nan into the demand array to cover future periods
#level (a), periodicity(p) and forecast (f)
a,p,f = np.full((3,cols+extra_periods),np.nan)
q = 1 #periods since last demand observation
# Initialization
first_occurence = np.argmax(d[:cols]>0)
a[0] = d[first_occurence]
p[0] = 1 + first_occurence
f[0] = a[0]/p[0]
# Create all the t+1 forecasts
for t in range(0,cols):
if d[t] > 0:
a[t+1] = alpha*d[t] + (1-alpha)*a[t]
p[t+1] = alpha*q + (1-alpha)*p[t]
f[t+1] = a[t+1]/p[t+1]
q = 1
else:
a[t+1] = a[t]
p[t+1] = p[t]
f[t+1] = f[t]
q += 1
# Future Forecast
a[cols+1:cols+extra_periods] = a[cols]
p[cols+1:cols+extra_periods] = p[cols]
f[cols+1:cols+extra_periods] = f[cols]
df = pd.DataFrame.from_dict({"Demand":a,"Forecast":f,"Period":p})
return df
Input = Alteryx.read("#1")
Output = Croston(Input)
Alteryx.write(Output,1)
Thank you both very much for looking at it and giving me the insight I needed.
Best,
Daniel