python实现趋势外推法


一、实验目的:

实现趋势外推法:一次、二次、三次等;
步骤:
1.收集研究对象的动态数列(自选);
2.画数据点分布图,判断近似曲线;
3.计算差分,确定曲线方程;
4.求曲线参数;
5.预测;

要求:
1.画出数据的散点图;
2.打印出差分:一阶、二阶、一阶差比率;
3.求出方差的参数;(t可以自取)
4.预测;

二、实验平台:

Python 3.7

三、实验内容与结果:

3.1 题目分析

找寻一个自己要预测的数据集,绘制散点图;
计算差分:一阶、二阶、一阶差比率;
在这里插入图片描述
一阶差比率为yy=Y(t)/Y(t-1)
求各个模型参数,这里的t我是按照ppt取中间的值为0,然后对称+1,-1.
在这里插入图片描述
则有,指数曲线Y=lga+lgb,预测值y=e**Y

3.2 代码

# -*- codeing =utf-8 -*-
# @Time : 2021/4/22 14:28
# @Author : ArLin
# @File : demo1.py
# @Software: PyCharm
import csv
from pylab import *
mpl.rcParams['font.sans-serif'] = ['SimHei']#正常显示汉字
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
#读取csv文件
def ReadCsvFile(path):
    File = open(path, 'r')
    f = csv.reader(File)
    i = 0
    data = []
    year=[]
    for row in f:
        if i > 0:#去头处理
            data.append(float(row[1]))
            year.append(float(row[0]))
        i = i + 1

    return year,data

#绘制散点图
def draw1(year,data):
    ryear=[]
    rdata=[]
    for index in range(len(year)):
        ryear.append(year[index])
        rdata.append(data[index])
    plt.figure(1)
    plt.title("1978-2010中国研究生招生数")
    plt.plot(ryear, rdata, '.')
    plt.xlabel('指标(年)')
    plt.ylabel('研究生招生数(万人)')
    plt.show()
    return ryear,rdata

def draw2(ryear,rdata):
    a1 = []
    a2 = []
    b = []
    for index in range(len(rdata)):
        # 一阶差分和一阶比率
        if index > 0:
            a1.append(rdata[index] - rdata[index - 1])
            # 一阶比率
            b1 = rdata[index] / rdata[index - 1]
            b.append(np.round(b1, 2))
    # 二阶差分
    for index in range(len(a1)):
        if index > 0:
            a2.append(a1[index] - a1[index - 1])
    plt.figure(2)
    plt.plot(a1, '--', label="一阶差分")
    plt.plot(a2, ':', label="二阶差分")
    plt.plot(b,'r', label="一阶差比率")
    plt.legend(["一阶差分", "二阶差分", "一阶差比率"])
    plt.show()


#求出方差的参数(取中间值为t,两边对称)
def forecast1(rdata):
    t = []
    Yt = []
    ysum = 0
    tyt = 0
    tsum = 0
    for index in range(len(rdata)):
        # 计算和t的平方
        t1 = (len(rdata) - 1) / 2 * -1 + index
        t.append(t1)
        tsum = tsum + t1 * t1
        # 计算Yt
        yt = math.log(rdata[index])
        ysum = ysum + yt
        Yt.append(np.round(yt, 2))
        # 计算lgb
        tyt = tyt + t[index] * yt
    # lga
    lga = np.round((ysum / len(rdata)), 2)
    print('lga的值',lga)
    # lgb
    lgb = np.round((tyt / tsum), 2)
    print('lgb的值',lgb)
    print("2021年的研究生招生人数:",e ** (lga + lgb *((len(rdata) - 1) / 2 * -1 + len(rdata)+1)))
    return lga,lgb,t

#1978-2010中国研究生招生数(预测值和真实值比较)
def forecast2(year1,data1,lga,lgb,t):
    fy=[]
    #预测值
    for i in t:
        z = e ** (lga + lgb * i)
        fy.append(np.round(z, 3))

    #图1
    plt.figure(3)
    plt.title("1978-2010中国研究生招生数(预测值和真实值比较)表一")
    plt.plot(year1,fy,'r',label="预测值")
    plt.plot(year1,data1, '.g',label="真实值")
    plt.legend(["预测试", "真实值"])
    plt.xlabel('指标(年)')
    plt.ylabel('研究生招生数(万人)')
    plt.show()

    #图二
    year2=[]
    for i in year1:
        year2.append(i+0.3)
    plt.figure(4)
    plt.title("1978-2010中国研究生招生数(预测值和真实值比较)表二")
    plt.bar(year1, fy, width=0.3, color='r',label="预测值")
    plt.bar(year2, data1,width=0.3,color='g',label="真实值")
    plt.legend(["预测试", "真实值"])
    plt.xlabel('指标(年)')
    plt.ylabel('研究生招生数(万人)')
    plt.show()

    #图三
    error=[]
    for index in range(len(data1)):
        error1=data1[index]-fy[index]
        if error1<0:
            error1=-1*error1
        error.append(error1)

    plt.figure(5)
    plt.title("1978-2010中国研究生招生数(预测值和真实值比较)表三")
    plt.bar(year1, error,  label="误差值")
    plt.legend(["误差值"])
    plt.xlabel('指标(年)')
    plt.ylabel('研究生招生数(万人)')
    plt.show()

3.3结果与分析:

结果截图:
散点图:
在这里插入图片描述
我选取的是1978-2020年中国研究生招生数的数据集,通过绘制的散点图,我们可以看出中国研究生招生数大致成指数分布,我们可以大胆的猜测可以使用指数曲线的模型来进行预测。
打印出差分:
在这里插入图片描述
通过差分表我们可以看出,一阶差分和二阶差分的波动幅度较大,一阶差比率基本相等,基本在0值附近成一条直线段,这个结果验证了中国研究生招生数成指数分布,我们可以使用指数曲线的模型来进行预测。
预测值:
在这里插入图片描述
1978-2010中国研究生招生数(预测值和真实值比较):
散点图:
在这里插入图片描述
条形图:
在这里插入图片描述
在这里插入图片描述

3.4实验总结

出现的问题与解决方法:
问题1:
程序报错:
TypeError: ufunc ‘bitwise_xor’ not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ‘‘safe’’
TypeError:输入类型不支持ufunc“按位\u xor”,并且无法根据强制转换规则“safe”将输入安全地强制为任何受支持的类型
代码行:

forecasty=e^(lga+lgb*1)

解决方法:
经过查询资料后,在python中要表示指数的形式应该为**,而不是^,之后把代码改成forecasty=e**(lga+lgb*1)方式就可通过
问题2:
我打印出来的表格刚开始是这样
在这里插入图片描述
非常乱码,而且也看不出来曲线的趋势
解决方法:
经过查询后,我发现我从csv读出来的数据是带‘’,也就是如图以字符串的形式存在
在这里插入图片描述
而我们需要把他们转成数据,我使用的是强制转换,如图:
在这里插入图片描述
在这里插入图片描述
则可以解决图表错乱

问题3:
刚开始我发现我的预测值特别不准,只有12万多,相比2020的110.7万相差的非常多
在这里插入图片描述
解决方法:
我先检查了我的代码,确保我的参数和公式是对的,接着我又检查了数据集,确定数据集也没问题后,我发现我的t值取错了
上面的错误预测值是因为我的t取了1这个值,而我前面说过我的t=0是在中间的值,也就是说我要预测2021年应该取t=22这个值

个人总结

本次的数据集要求自己去选取的,我就在国家统计局的官网选取了1978-2020年中国研究生招生数的数据集来进行预测
本次的实验和上次的实验三有类似之处,要对数据进行判断进行分析预测的模型,求出参数,带入预测模型,然后进行预测
使用的知识点基本也都是matplotlib+numpy,不同的是相较于上一次的实验,我这次对于数据的处理比较偏向可视化,用了散点-折线图和条形图来展现结果,这样更加具像。

(努力学习才能变成像罗翔老师一样优秀的人,定下目标后,只要实现就好了。冲冲冲!!!

  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值