数据自己录入啦。
4
相关库的引入
我们现在在之前第2点建立的文件的基础上进行修改,
在forecasting.py的头部引入以下库
# -*- coding: utf- 8-*-from app importappfrom flask importrender_templateimportpylabimportpandas as pdimportnumpy as npfrom pandas importSeries,DataFrameimportMySQLdbimportpandas.io.sql as sqlimportstatsmodels.api as smimporttimeimportdatetimefrom dateutil.relativedelta importrelativedeltaimportrandom
5
定义路由
@app.route( '/forecasting/')
意思就是我们访问例如http://127.0.0.1:5000/forecasting/2的地址对于就是解析到forecasting.py文件, 其中是可变的URL部分,如上面的URL的2
6
定义函数
defforecasting(lag=None):
其中lag就是接受URL中的参数,我们定义lag是自回归函数的滞后期数。
7
数据库连接
conn= MySQLdb.connect(host= '127.0.0.1',user= 'root',passwd= '123456',db= 'bi',charset= 'utf8')str_sql= "select SaleMonth as Month,Sale from sale order by SaleMonth"sale=sql.read_sql(str_sql,conn)
8
数据处理
我们整理数据以适合使用。
##//数据处理#转换数据中的月份为日期类型,并把它定义为pandas索引sale.Month = pd.to_datetime(sale.Month)sale = sale.set_index("Month")##//提取最大月份和最小月份start= min(sale.index)end= max(sale.index)##定义预测的月份,在最大月份的基础上加1-4pre_start = end+relativedelta( months= 1)pre_end = end+relativedelta( months= 4)#必要的转换pre_start =pre_start.strftime( '%Y-%m-%d')pre_end =pre_end.strftime( '%Y-%m-%d')#生成时间序列,从最小月份到最大月份i = pd.date_range( start, end, freq= 'MS')df = DataFrame(i,i)#定义列、定义索引index名df.columns = [ 'T']df.index.names =[ 'Month']#把sale与df合并,通过索引rs = pd.merge(sale,df,left_index= True,right_index= True,how= 'outer')#删除临时列T,并把rs转换为html,方便后面输出到模版中del rs[ 'T']data= rs.to_html
9
数据预测
##预测#对rs进行对数变换rs= np.log(rs)#对rs进行自回归,lag是自回归的滞后因子,来自函数的lag参数,即来自RUL的参数r= sm.tsa.AR(rs).fit(maxlag=lag, method='mle', disp=-1)#对未来四个月进行预测fcst_lg= r.predict(start,pre_end)#对预测的结果进行指数变换,因为之前做了对数变换fcst= np.exp(fcst_lg)#转换fcst为pandas的DataFrame格式fcst= DataFrame(fcst)#定义列名和索引,用于和原来的rs合并fcst.columns= ['fcst']fcst.index.names= ['Month']#合并fcst和rs到rs_outrs_out= pd.merge(sale,fcst,left_index = True,right_index = True,how='outer')#rs_out转换为记录格式,再转换为html格式,以方便输出到模版中显示#取得最后的4行作为预测的显示输出,不知道为什么rs_out[-4:-1]这个输出漏了最后一行rs_fcst= rs_out[-4:-1]rs_fcst= rs_fcst.to_htmlrs2= rs_out.to_recordsrs_out= rs_out.to_html
10
数据整理
我使用了echart web图标框架进行显示。
##以下是处理表格数据输出到echart的json格式tmp= u""tmp1= ""tmp2= ""tmp3= ""fort inrs2:#tmp1 += "{'label':'" + str(t.Month.year)+"/"+str(t.Month.month) + "','value':'" + str(t.Qty) + "'},"#tmp1 += ""tmp1 += "'"+str(t.Month.year)+ "/"+str(t.Month.month)+ "',"#tmp2 += ""tmp2 += str( '%.0f'% t.Sale) + ","#tmp3 += ""tmp3 += str( '%.0f'% t.fcst) + ","tmp += ""+tmp1+ ""tmp += u""+tmp2+ ""tmp += u""+tmp3+ ""+ ""tmp1 = tmp1[: -1]tmp2 = tmp2[: -1]tmp2 = tmp2.replace( 'nan', ''- '')tmp3 = tmp3[: -1]tmp= u'''{title : {text: '测试',subtext: '纯属虚构'},tooltip : {trigger: 'axis'},legend: {data:['实际销售','预测销售']},toolbox: {show : true,feature : {mark : {show: false},dataView : {show: true, readOnly: false},magicType : {show: true, type: ['line', 'bar']},restore : {show: true},saveAsImage : {show: false}}},calculable : true,dataZoom : {show : true,realtime : true,start : 0,end : 100},xAxis : [{type : 'category',data : [%s]}],yAxis : [{type : 'value',min : 5000,scale : true}],series : [{name:'实际销售',type:'bar',data:[%s],markPoint : {data : [{type : 'max', name: '最大值'},{type : 'min', name: '最小值'}]},markLine : {data : [{type : 'average', name: '平均值'}]}},{name:'预测销售',type:'line',data:[%s],}]};'''%(tmp1,tmp2,tmp3)
11
生成公式
生成一个公式能更直观显示变量之间的关系。
#生成动态公式图片rp = r.paramsftext= ''i= 0forrp1 inrp:if(i== 0) and(rp1> 0) :const = '+'+ str(( "%.4f"% rp1))if(i== 0) and(rp1< 0) :const = str(( "%.4f"% rp1))if(i== 1):ftext = ftext + str(( "%.4f"% rp1))+ 'y_{t-'+str(i)+ '}'if(i> 1) and(rp1> 0):ftext = ftext + '+'+ str(( "%.4f"% rp1))+ 'y_{t-'+str(i)+ '}'if(i> 1) and(rp1< 0):ftext = ftext + str(( "%.4f"% rp1))+ 'y_{t-'+str(i)+ '}'i += 1f = r'$y_{t}='+ftext+const + '$'f2 = r'$y=ln(w_{t})$'fig = pylab.figure#设置背景为透明fig.patch.set_alpha( 0)text = fig.text( 0, 0, f)# 把公式用公式图片的方式保存dpi = 300fig.savefig( 'd:/py/formula.png', dpi=dpi)# Now we can work with text's bounding box.bbox = text.get_window_extentwidth, height = bbox.size / float(dpi/ 4) + 0.005# Adjust the figure size so it can hold the entire text.fig.set_size_inches((width, height))# Adjust text's vertical position.dy = (bbox.ymin/float(dpi))/heighttext.set_position(( 0, -dy))# Save the adjusted text.url = 'D:/py/Flask/app/static/images/1.png'fig.savefig(url, dpi=dpi)
12
输出到模板
把py程序中的在模版中用到的结果输出到模版。
#生成动态公式图片rp = r.paramsftext= ''i= 0forrp1 inrp:if(i== 0) and(rp1> 0) :const = '+'+ str(( "%.4f"% rp1))if(i== 0) and(rp1< 0) :const = str(( "%.4f"% rp1))if(i== 1):ftext = ftext + str(( "%.4f"% rp1))+ 'y_{t-'+str(i)+ '}'if(i> 1) and(rp1> 0):ftext = ftext + '+'+ str(( "%.4f"% rp1))+ 'y_{t-'+str(i)+ '}'if(i> 1) and(rp1< 0):ftext = ftext + str(( "%.4f"% rp1))+ 'y_{t-'+str(i)+ '}'i += 1f = r'$y_{t}='+ftext+const + '$'f2 = r'$y=ln(w_{t})$'fig = pylab.figure#设置背景为透明fig.patch.set_alpha( 0)text = fig.text( 0, 0, f)# 把公式用公式图片的方式保存dpi = 300fig.savefig( 'd:/py/formula.png', dpi=dpi)# Now we can work with text's bounding box.bbox = text.get_window_extentwidth, height = bbox.size / float(dpi/ 4) + 0.005# Adjust the figure size so it can hold the entire text.fig.set_size_inches((width, height))# Adjust text's vertical position.dy = (bbox.ymin/float(dpi))/heighttext.set_position(( 0, -dy))# Save the adjusted text.url = 'D:/py/Flask/app/static/images/1.png'fig.savefig(url, dpi=dpi)
13
设计模板
我们可以用 {{变量名}}来接受来自py程序的变量。
< title>分析结果 title>< type= "text/java"src= "{{url_for('static', filename='ECharts/doc/asset/js/esl/esl.js')}}"> >< type= "text/java">// 路径配置require.config({paths:{'echarts': '/static/ECharts/build/echarts','echarts/chart/bar': '/static/ECharts/build/echarts','echarts/theme/macarons': '/static/ECharts/src/theme/macarons',}});require(['echarts','echarts/theme/macarons','echarts/chart/bar', // 使用柱状图就加载bar模块,按需加载'echarts/chart/line'// 使用柱状图就加载bar模块,按需加载],function( ec,theme){// 基于准备好的dom,初始化echarts图表varmyChart = ec.init( document.getElementById( 'main'),theme);varoption = {{tmp | safe}}myChart.setOption(option);}); >< style>.right{ text-align: right}body{ font-size: 12px; background:white} style>< divstyle= "width:970px;">< divid= "main"style= "float:left;height:300px;width:600px;"> div>< divstyle= "float:left;height:300px;width:350px;margin-left:10px;">Summary of AR Results< tableborder= 0style= "width:200px">< tr>< tdcolspan= 2> td> tr>< tr>< td>Lag length: td>< tdclass= 'right'>{{r.k_ar}} td> tr>< tr>< td>Samples: td>< tdclass= 'right'>{{r.nobs}} td> tr>< tr>< td>Model: td>< tdclass= 'right'>AR td> tr> table>----------------------------------------- < br>< tableborder= 0style= "width:350px">< tr>< td>AIC: td>< tdclass= 'right'>{{'%.4f' % r.aic}} td>< td>BIC: td>< tdclass= 'right'>{{'%.4f' % r.bic}} td> tr>< tr>< td>FPE: td>< tdclass= 'right'>{{'%.4f' % r.fpe}} td>< td>HQIC: td>< tdclass= 'right'>{{'%.4f' % r.hqic}} td> tr> table>---------------------------------------------------------- < br>Results for equation < br>========================================================== < br>< tableborder= 0style= "width:280px">< trstyle= "border-bottom:1px solid red">< td>X td>< tdclass= 'right'>coefficient td>< tdclass= 'right'>std.error td>< tdclass= 'right'>t-stat td>< tdclass= 'right'>p-value td> tr>{% for i in range(lag+1) %}< tr>{% if i==0 %}< td>const td>{% else %}< td>Y(t-{{i}}) td>{% endif %}< tdclass= 'right'>{{'%.4f' % r.params[i]}} td>< tdclass= 'right'>{{'%.4f' % r.bse[i]}} td>< tdclass= 'right'>{{'%.4f' % r.tvalues[i]}} td>< tdclass= 'right'>{{'%.4f' % r.pvalues[i]}} td> tr>{% endfor %} table>---------------------------------------------------------- < br>预测 < br>========================================================== < br>{{rs_fcst | safe}} div> div>< divstyle= "width:970px;margin-bottom:10px;">< imgheight= 24src= "../../../static/images/1.png?">< br>
14
实际应用
在这个例子中,我们只是对一个产品、一个模型、一个参数进行了预测。
在实际应用中, 可以批量对产品、多个模型、多种参数进行预测,写一个判定预测模型好坏的算法,自动确定每种产品的最优模型和参数,定期自动计算各产品的预测值。
希望这个思路能帮到大家。
作者:梁斌炜
来源:http://www.statr.cn/?p=205
本文为转载分享,如有侵权请联系后台删除
点分享
点点赞