设为首页 收藏本站
查看: 3689|回复: 0

[经验分享] 二次指数平滑预测法 Python实现

[复制链接]

尚未签到

发表于 2015-11-30 10:59:06 | 显示全部楼层 |阅读模式
  从以往的时间序列值,进行指数平滑,做两次预测出下一个时间的估计值。
  
  目录结构如下:
DSC0000.png
  
  Python代码如下:
  forecast.py



# -*-coding:utf-8 -*-
# Time:2015.11.25 sangjin
__author__ = 'hunterhug'
import matplotlib
#matplotlib.use("Agg")
#matplotlib.use("TkAgg")
#matplotlib.use("gtk")
import matplotlib.pyplot as plt
from matplotlib.pyplot import savefig  
from matplotlib.font_manager import FontProperties
from operator import itemgetter
#读取execel使用(支持07)
from openpyxl import Workbook
#写入excel使用(支持07)
from openpyxl import load_workbook
import os

def judgefile():
path = input("请输入该目录下的excel文件名:") # file path
if os.path.isfile(path):
return path.lower()
else:
print("文件不存在")
return judgefile()
def writeexcel07(path, content, name='Sheet1', sheetnum=0):
wb=Workbook()
#sheet=wb.add_sheet("xlwt3数据测试表")
sheet=wb.create_sheet(sheetnum,name)
# values = [["名称", "hadoop编程实战", "hbase编程实战", "lucene编程实战"], ["价格", "52.3", "45", "36"], ["出版社", "机械工业出版社", "人民邮电出版社", "华夏人民出版社"], ["中文版式", "中", "英", "英"]]
for i in range(0,len(content)):
for j in range(0,len(content)):
sheet.cell(row = i+1,column= j+1).value = content[j]
# sheet.cell(row = 1,column= 2).value="温度"
    wb.save(path)
print("写入数据成功!")
def read07excel(path):
excelcontent = []
wb2=load_workbook(path)
sheetnames = wb2.get_sheet_names()
ws=wb2.get_sheet_by_name(sheetnames[0])
row=ws.get_highest_row()
col=ws.get_highest_column()
# print("列数: ",ws.get_highest_column())
# print("行数: ",ws.get_highest_row())
for i in range(0,row):
rowcontent = []
for j in range(0,col):
if ws.rows[j].value:
rowcontent.append(ws.rows[j].value)
excelcontent.append(rowcontent)
print("读取数据成功!")
return excelcontent

def calvalue(excel, a):
date = [] # x label date
data = [] # y label data
for i in range(2,len(excel)-1):
data.append(float(excel[1]))
date.append(excel[0])
e1 = [data[0]] # one time forecast
for i in range(0,len(data)):
next = data * a + e1 * (1 - a)
e1.append(next)
e1e = [] # one time absoultion error
for i in range(0,len(data)):
e1e.append(abs(data-e1))
e1e2 = sum(e1e)
e2 = [data[0]] # second time forecast
for i in range(0,len(data)):
next = e1 * a + e2 * (1 - a)
e2.append(next)
e2e = [] # second time absoultion error
for i in range(0,len(data)):
e2e.append(abs(data-e2))
e2e2 = sum(e2e)
e1y = e1[len(e1)-1] # one time forecast value
e2y = e2[len(e2)-1] # two time forecast value
return [a, e1y, e2y, e1e2, e2e2]
def calvaluetop5(excel, step = 0.01):
initvalue = 1.0
all = []
top5 =[]
while initvalue <= 1.0 and initvalue >= 0:
all.append(calvalue(excel, initvalue))
initvalue = initvalue -step
d = {}
for i in range(0, len(all)):
d.setdefault(i, all[3])
d1 = sorted(d.items(), key=itemgetter(1))
#print(d1)
topnum = len(d1)
if topnum>=5:
topnum = 5
else:
pass
for i in range(0,topnum):
pos = d1[0]
top5.append(all[pos])
return top5
def judgestep():
try:
a = float(input("请选择系数变化步长(范围0~1):"))            # change var
except:
print("请输入数字好么...")
return judgestep()
while a > 1 or a < 0:
print('输入的步长范围在0-1之间')
return judgestep()
return a
def judge():
try:
a = float(input("请输入变化系数a:"))            # change var
except:
print("请输入数字好么...")
return judge()
while a > 1 or a < 0:
print('输入的变化系数范围在0-1之间')
return judge()
return a

def single(a,path):
excel = read07excel(path)
title1 = excel[0][0]
title2 = excel[1]
# print(excel)

title = ':'.join(excel[0])
date = [] # x label date
data = [] # y label data
for i in range(2,len(excel)-1):
data.append(float(excel[1]))
date.append(excel[0])
# print('/n',data)
# print(title,data,date)

e1 = [data[0]] # one time forecast
for i in range(0,len(data)):
next = data * a + e1 * (1 - a)
e1.append(next)
# print('/n',e1)

e1e = [] # one time absoultion error
for i in range(0,len(data)):
e1e.append(abs(data-e1))
# print('/n',e1e)

ele2 = sum(e1e)
# print(ele2)

e2 = [data[0]] # second time forecast
for i in range(0,len(data)):
next = e1 * a + e2 * (1 - a)
e2.append(next)
# print('/n',e2)

e2e = [] # second time absoultion error
for i in range(0,len(data)):
e2e.append(abs(data-e2))
# print('/n',e2e)

e2e2 = sum(e2e)
# print(e2e2)

e1y = e1[len(e1)-1] # one time forecast value
e2y = e2[len(e2)-1] # two time forecast value

content = [[title1,'可变系数a=',a]]
content.append([title2[0],title2[1],'一次指数平滑预测值','绝对误差','二次指数平滑','绝对误差'])
datas = [date, data, e1[:len(e1)-1], e1e, e2[:len(e2)-1], e2e]
datast = [[r[col] for r in datas] for col in range(len(datas[0]))]
content[len(content):] = datast
yu1 = ['', e2y, e1y, ele2, e2y, e2e2]
yu2 = ['', '最终预测值', '一次指数平滑预测值', '一次指数平滑绝对误差累加', '二次指数平滑预测值', '一次指数平滑绝对误差累加']
content.append(yu1)
content.append(yu2)
content.append(['说明:请手动插入走势图。此文件为自动计算生成'])
# print(content)

path1 =path.replace('.xlsx', '(结果生成).xlsx')
writeexcel07(path1, content, '生成表')
print("请打开所在目录生成的excel文件(结果生成)")
plt.close('all')
font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14)
plt.figure(figsize=(10,7))
num = range(0,len(date))
plt.plot(num, data, 'b-*', label='原始数据')
plt.plot(num, e1[:len(e1)-1], 'r*-', label='一次指数预测')
plt.plot(num, e2[:len(e2)-1], 'g*-', label='二次指数预测')
bottomtitle1 = '\n一次预测值:'+str(e1y)+"\t误差和:"+str(ele2)
bottomtitle = bottomtitle1 + '\n二次预测值:'+str(e2y)+"\t误差和:"+str(e2e2)
plt.title('指数平滑法预测走势图(时间序列)变化系数a={0:3f}'.format(a)+bottomtitle, fontproperties=font) # simfang.ttf
# plt.text(0, 0, bottomtitle, fontproperties=font)
plt.xlabel('时间间隔', fontproperties=font)
plt.ylabel('成交额', fontproperties=font)
legend = plt.legend(loc='upper right', prop=font)
# legend = plt.legend(loc='upper right', shadow=True, prop=font)
legend.get_frame().set_facecolor('white')
plt.grid(True)
# Tweak spacing to prevent clipping of ylabel
plt.subplots_adjust(left=0.15)
plt.show()
savefig('Fig.png')

def begin():
sangjin = '''
-----------------------------------------
| 欢迎使用二次指数平滑法预测未来值    |
|                                    |
| 使用方法:                         |
| 1.根据提示进行操作                |
| 2.输出为预测走势图,以及处理后的excel    |
-----------------------------------------
| 青木公司花名:桑槿            |
| 新浪微博:一只尼玛              |
| 微信/QQ:569929309            |
-----------------------------------------
'''
print(sangjin)
def loop(path):
choice1 = input("自动计算变化系数请选择y,手动请选择n\n")
if choice1 == 'y':
step = judgestep()
p5 = calvaluetop5(read07excel(path), step)
print('总误差最小的前五个是')
for i in p5:
print('变化系数:{0:3f}\t预测值:{1:3f}\t总误差值:{2:3f}'.format(i[0],i[2],i[4]))
single(p5[0][0],path)
else:
a = judge()
single(a,path)

def loop3(path):
choice2 = input("如果想操作其他文件请选择y,退出选择n,其他操作按任意键\n")
if choice2 == 'y':
loop1()
elif choice2 == 'n':
print("正在退出中...\n"*6)
print("正在退出中...谢谢")
exit(1)
else:
loop(path)
loop3(path)
def loop1():
path = judgefile()
loop(path)
loop3(path)
begin()
loop1()

  
  输入excel格式如下:
DSC0001.png
  
  输出结果:
DSC0002.png
DSC0003.png
  代码参考:
  下载

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-145301-1-1.html 上篇帖子: 22 扩展Python 下篇帖子: Python学习(四)数据结构 —— str
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表