|
|
<template>
|
|
|
<!-- <el-scrollbar ref="scrollbar" height="800px"> -->
|
|
|
<div class="main-top">
|
|
|
<span style="font-weight: bold; font-size: 18px; color: #3596eb">任务描述</span>
|
|
|
<p style="font-weight: 400; font-size: 12px; color: #e6e6e6">使用“销售预测数据”,建立回归模型,并预测销量是84610下的销售额,最后提交实训任务。</p>
|
|
|
</div>
|
|
|
<div class="main-but">
|
|
|
<el-button @click="runResultShow = true">
|
|
|
<img src="../../../assets/images/导入.png" alt="" />
|
|
|
算法知识导入
|
|
|
</el-button>
|
|
|
<el-button @click="taskSubmit">
|
|
|
<img src="../../../assets/images/提交.png" alt="" />
|
|
|
实训任务提交
|
|
|
</el-button>
|
|
|
</div>
|
|
|
<div class="app-main">
|
|
|
<div class="main-left">
|
|
|
<el-scrollbar height="640px" style="padding: 0 10px" min-size="5">
|
|
|
<div>
|
|
|
<div class="left-top">
|
|
|
<span>一、选择指标</span>
|
|
|
</div>
|
|
|
<div class="metrics">
|
|
|
<el-select v-model="input" placeholder="请选择" style="width: 180px" @change="optionData">
|
|
|
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
</el-select>
|
|
|
</div>
|
|
|
<div class="metrics-table" style="margin-top: 10px">
|
|
|
<el-table border :data="tableData" style="width: 100%" :header-cell-style="headerCellStyle" @selection-change="handleSelectionChange">
|
|
|
<el-table-column type="selection" label="Date" align="center" :selectable="flag" />
|
|
|
<el-table-column prop="text" label="指标" align="center" />
|
|
|
</el-table>
|
|
|
<el-button @click="taskZB">确定</el-button>
|
|
|
</div>
|
|
|
<div class="left-top" style="margin-top: 50px">
|
|
|
<span>二、数据预处理</span>
|
|
|
</div>
|
|
|
<div class="metrics">
|
|
|
<el-select v-model="input2" @change="optionData2" placeholder="请选择" style="width: 180px">
|
|
|
<el-option v-for="item in options2" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
</el-select>
|
|
|
</div>
|
|
|
<div class="metrics" style="margin-top: 15px">
|
|
|
<el-select v-model="input3" @change="optionData2" placeholder="请选择" style="width: 180px">
|
|
|
<el-option v-for="item in options3" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
</el-select>
|
|
|
</div>
|
|
|
<div class="left-top" style="margin-top: 50px">
|
|
|
<span>三、模型参数设置</span>
|
|
|
</div>
|
|
|
<div class="metrics-table" style="margin-top: 10px">
|
|
|
<span style="font-weight: 400; font-size: 12px; color: #ffffff">回归模型:</span>
|
|
|
<div class="metrics" style="margin-top: 10px">
|
|
|
<el-select v-model="input4" placeholder="请选择" style="width: 180px">
|
|
|
<el-option v-for="item in options4" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
</el-select>
|
|
|
</div>
|
|
|
<div class="metrics2" style="margin-top: 10px">
|
|
|
<span style="font-weight: 400; font-size: 12px; color: #ffffff">Y变量选择:</span>
|
|
|
<!-- <el-input v-model="input5" style="width: 160px;margin-top:5px"/> -->
|
|
|
<el-select v-model="input5" multiple placeholder="请选择" style="width: 180px">
|
|
|
<el-option v-for="item in option5" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
</el-select>
|
|
|
</div>
|
|
|
<div class="metrics2" style="margin-top: 10px">
|
|
|
<span style="font-weight: 400; font-size: 12px; color: #ffffff">X变量选择:</span>
|
|
|
<!-- <el-input v-model="input6" style="width: 160px;margin-top:5px"/> -->
|
|
|
<el-select v-model="input6" multiple placeholder="请选择" style="width: 180px">
|
|
|
<el-option v-for="item in option5" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
</el-select>
|
|
|
</div>
|
|
|
<el-button @click="computation">计算</el-button>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div style="margin-top: auto">
|
|
|
<div class="startOver" @click="startOver()">
|
|
|
<img src="../../../assets/images/重新开始.png" alt="" />
|
|
|
<span>重新开始</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-scrollbar>
|
|
|
|
|
|
</div>
|
|
|
<div class="main-right">
|
|
|
<el-scrollbar height="500px" ref="scrollbar" style="padding: 20px">
|
|
|
<div>
|
|
|
<span style="font-weight: bold; font-size: 18px; color: #3596eb">分析数据:</span>
|
|
|
<el-table :data="tableData2" style="width: 98%; margin-top: 10px" :header-cell-style="headerCellStyle" height="350">
|
|
|
<el-table-column v-for="column in tableLabel" :key="column.prop" :prop="column.prop" :label="column.label" align="center" />
|
|
|
</el-table>
|
|
|
<!-- <el-pagination style="margin-top:10px" background layout="prev, pager, next" :total="1000" /> -->
|
|
|
</div>
|
|
|
<div class="analysisResults" style="margin-top: 20px">
|
|
|
<span style="font-weight: bold; font-size: 18px; color: #3596eb; display: block">分析结果:</span>
|
|
|
<el-button class="imgBtn" v-if="flagUP" @click="upLoad">下载</el-button>
|
|
|
<el-table :data="tableData3" v-loading="loading1" ref="exportTableRef" row-key="TSuid" style="width: 98%; margin-top: 10px" :header-cell-style="headerCellStyle" height="350">
|
|
|
<el-table-column v-for="column in tableLabel2" :key="column.prop" :prop="column.prop" :label="column.label" align="center" />
|
|
|
<el-table-column v-if="flagColumn" label="预测" align="center">
|
|
|
<template #default="scope">
|
|
|
<el-button type="primary" link @click="handleClick(scope.row)" v-if="predictionResults === ''">预测</el-button>
|
|
|
<span v-else>{{ predictionResults }}</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
</div>
|
|
|
</el-scrollbar>
|
|
|
</div>
|
|
|
</div>
|
|
|
<!-- </el-scrollbar> -->
|
|
|
|
|
|
<el-dialog v-model="dialogVisible" title="实训任务提交" width="600" custom-class="dialogClass" :show-close="false">
|
|
|
<template #header="{ close, titleId, titleClass }">
|
|
|
<div class="my-header">
|
|
|
<span :id="titleId" :class="titleClass">实训任务提交</span>
|
|
|
<img class="gbImg" src="../../../assets/images/关闭.png" @click="close" alt="" />
|
|
|
</div>
|
|
|
<img class="xtImg" src="../../../assets/images/线条.png" alt="" />
|
|
|
</template>
|
|
|
<div class="from-item">
|
|
|
<el-form :inline="true" label-position="right" label-width="185px" :model="form" class="demo-form-inline">
|
|
|
<el-form-item label="回归方程常数项值:">
|
|
|
<el-input style="width: 220px" v-model="formInline3.value1" clearable />
|
|
|
</el-form-item>
|
|
|
<el-form-item label="回归方程系数值:">
|
|
|
<el-input style="width: 220px" v-model="formInline3.value2" clearable />
|
|
|
</el-form-item>
|
|
|
<el-form-item label="预测值:">
|
|
|
<el-input style="width: 120px" v-model="formInline3.value3" clearable />
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
</div>
|
|
|
<template #footer>
|
|
|
<div class="dialog-footer">
|
|
|
<el-button @click="task()">确定</el-button>
|
|
|
<el-button type="primary" @click="dialogVisible = false">返回</el-button>
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
|
|
|
<el-dialog v-model="dialogVisible2" title="预测" width="400" custom-class="dialogClass" :show-close="false">
|
|
|
<template #header="{ close, titleId, titleClass }">
|
|
|
<div class="my-header">
|
|
|
<span :id="titleId" :class="titleClass">预测</span>
|
|
|
<img class="gbImg" src="../../../assets/images/关闭.png" @click="close" alt="" />
|
|
|
</div>
|
|
|
<img class="xtImg" src="../../../assets/images/线条.png" alt="" />
|
|
|
</template>
|
|
|
<div class="from-item">
|
|
|
<el-form :inline="true" label-position="right" label-width="50px" :model="form" class="demo-form-inline">
|
|
|
<el-form-item label="x:">
|
|
|
<el-input style="width: 225px" v-model="formInline2.user" clearable placeholder="请输入x" />
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
</div>
|
|
|
<template #footer>
|
|
|
<div class="dialog-footer">
|
|
|
<el-button @click="Forecasting">确定</el-button>
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
|
|
|
<pop-model :showModel="runResultShow" title="关联规则挖掘" @closePop="runResultShow = false">
|
|
|
<template v-slot:content>
|
|
|
<div>
|
|
|
<p style="font-weight: 700; font-size: 22px">变量间的关系的度量</p>
|
|
|
<p style="font-size: 19px; font-weight: 600">变量间的关系</p>
|
|
|
<li>函数关系:设有两个x和y,y随x一起变化,并完全依赖于x,y是x的函数,y = f ( x ) y = f(x)y=f(x),x为自变量,y为因变量。</li>
|
|
|
<li>相关关系:变量之前存在的不确定的关系称为相关关系。</li>
|
|
|
<p>
|
|
|
1.一个变量的取值不能由另一个变量唯一确定
|
|
|
<br />
|
|
|
2.当变量x 取某个值时,变量y 的取值对应着一个分布
|
|
|
<br />
|
|
|
3.各观测点分布在直线周围
|
|
|
</p>
|
|
|
<p style="font-size: 19px; font-weight: 600">相关关系的描述与测量</p>
|
|
|
<li>散点图:可以通过散点图判断两个变量之间有无相关关系,并对变量间的关系形态做出大致的描述。</li>
|
|
|
<img src="@/assets/images/f3001.png" alt="" style="height:500px"/>
|
|
|
<li>相关系数:是度量变量之间线性关系强度的一个统计量。</li>
|
|
|
<p>
|
|
|
若相关系数是根据总体全部数据计算的,称为总体相关系数,记为ρ;
|
|
|
<br />
|
|
|
若是根据样本数据计算的,则称为样本相关系数,简称为相关系数,记为 r rr,也称为Pearson \textbf{Pearson}Pearson相关系数或者线性相关系数。
|
|
|
</p>
|
|
|
<img src="@/assets/images/f3002.png" alt="" />
|
|
|
<br />
|
|
|
<p>
|
|
|
相关系数r rr 的性质:
|
|
|
<br />
|
|
|
r 的取值范围为 [ 0 , 1 ] [0,1][0,1];
|
|
|
</p>
|
|
|
<img src="@/assets/images/f3003.png" alt="" />
|
|
|
<p>
|
|
|
r 具有对称性。即x与y之间的相关系数和y与x之间的相关系数相等,即r x y = r y x r_{xy}= r_{yx}r
|
|
|
<br />
|
|
|
r 数值大小与x和y原点及尺度无关,即改变x和y的数据原点及计量尺度,并不改变r数值大小
|
|
|
<br />
|
|
|
r 仅仅是x与y之间线性关系的一个度量,它不能用于描述非线性关系。这意味着, r=0只表示两个变量之间不存在线性相关关系,并不说明变量之间没有任何关系 r 虽然是两个变量之间线性关系的一个度量,却不一定意味着x与y一定有因果关系
|
|
|
</p>
|
|
|
<img src="@/assets/images/f3005.png" alt="" />
|
|
|
<p style="font-size: 19px; font-weight: 600">相关关系的显著性检验</p>
|
|
|
<p>
|
|
|
检验两个变量之间是否存在线性相关关系,通常将 r rr 作为 ρ ρρ 的估计值。
|
|
|
<br />
|
|
|
r 的抽样分布(不写)
|
|
|
<br />
|
|
|
r 的显著性检验
|
|
|
</p>
|
|
|
<img src="@/assets/images/f3006.png" alt="" />
|
|
|
<p style="font-size: 19px; font-weight: 600">一元线性回归的估计和检验</p>
|
|
|
<li>相关分析目的在于用相关系数测度变量之间的关系强度。</li>
|
|
|
<li>而回归分析侧重于考察变量之间的数量关系,并通过一定的数学表达式将这种关系描述出来,从而确定一个或几个变量(自变量)的变化对另一个特定变量(因变量)的影响程度。具体来说,回归分析具体解决以下几个方面的问题:</li>
|
|
|
<p>
|
|
|
1.从一组样本数据出发,确定变量之间的数学关系式。
|
|
|
<br />
|
|
|
2.对这些关系式的可信程度进行各种统计检验,并从影响因变量的诸多变量中找出哪些变量的影响是显著的,哪些是不显著的。
|
|
|
<br />
|
|
|
3.利用所求的关系式,根据一个或几个自变量的取值来估计或预测因变量的取值,并给出这种估计或预测的可靠程度。
|
|
|
</p>
|
|
|
<li>在回归分析中:</li>
|
|
|
<p>
|
|
|
被预测或被解释的变量称为因变量,用y表示;
|
|
|
<br />
|
|
|
用来预测或被解释的一个或多个变量称为自变量,用x表示;
|
|
|
</p>
|
|
|
<p style="font-size: 16px; font-weight: 600">相关关系的显著性检验</p>
|
|
|
<p>检验两个变量之间是否存在线性相关关系,通常将 r rr 作为 ρ ρρ 的估计值。</p>
|
|
|
<img src="@/assets/images/f3007.png" alt="" />
|
|
|
<p style="font-size: 19px; font-weight: 600">一元线性回归的估计和检验</p>
|
|
|
<li>相关分析目的在于用相关系数测度变量之间的关系强度。</li>
|
|
|
<li>而回归分析侧重于考察变量之间的数量关系,并通过一定的数学表达式将这种关系描述出来,从而确定一个或几个变量(自变量)的变化对另一个特定变量(因变量)的影响程度。具体来说,回归分析具体解决以下几个方面的问题:</li>
|
|
|
<p>
|
|
|
1.从一组样本数据出发,确定变量之间的数学关系式。
|
|
|
<br />
|
|
|
2.对这些关系式的可信程度进行各种统计检验,并从影响因变量的诸多变量中找出哪些变量的影响是显著的,哪些是不显著的。
|
|
|
<br />
|
|
|
3.利用所求的关系式,根据一个或几个自变量的取值来估计或预测因变量的取值,并给出这种估计或预测的可靠程度。
|
|
|
</p>
|
|
|
<li>在回归分析中:</li>
|
|
|
<p>
|
|
|
被预测或被解释的变量称为因变量,用y表示;
|
|
|
<br />
|
|
|
用来预测或被解释的一个或多个变量称为自变量,用x表示;
|
|
|
</p>
|
|
|
<p style="font-size: 19px; font-weight: 600">一元线性回归模型</p>
|
|
|
<p>涉及一个自变量的回归。</p>
|
|
|
<li>回归模型:描述因变量y 如何依赖于自变量x 和误差项 ε εε 的方程称为回归模型,一元线性回归模型可表示为:</li>
|
|
|
<img src="@/assets/images/f3008.png" alt="" />
|
|
|
<li>上述模型称为理论回归模型,对于这一模型,有以下几个假定:</li>
|
|
|
<p>
|
|
|
1.因变量y与自变量x之间具有线性关系;
|
|
|
<br />
|
|
|
2.在重复抽样中,自变量x的取值是固定的,即假定x是非随机的;
|
|
|
<br />
|
|
|
3.对于满足:
|
|
|
</p>
|
|
|
<img src="@/assets/images/f3009.png" alt="" />
|
|
|
<li>回归方程 :描述因变量y的期望值如何依赖于自变量x的方程称为回归方程,一元线性回归方程的形式为:</li>
|
|
|
<img src="@/assets/images/f3010.png" alt="" />
|
|
|
<img src="@/assets/images/f3011.png" alt="" />
|
|
|
<p style="font-size: 19px; font-weight: 600">参数的最小二乘估计</p>
|
|
|
<img src="@/assets/images/f3012.png" alt="" />
|
|
|
<br />
|
|
|
<img src="@/assets/images/f3013.png" alt="" style="height: 400px;width: 400px;"/>
|
|
|
<br />
|
|
|
<img src="@/assets/images/f3014.png" alt="" />
|
|
|
<p style="font-size: 19px; font-weight: 600">回归直线的拟合优度</p>
|
|
|
<p>估计或预测的精度如何,将取决于回归直线对观测数据的拟合程度。各观测点越是紧密围绕直线,说明对观测数据的拟合程度越好,反之越差。</p>
|
|
|
<img src="@/assets/images/f3015.png" alt="" />
|
|
|
<li>总平方和(S S T SSTSST):反映因变量的n 个观察值与其均值的总误差。</li>
|
|
|
<img src="@/assets/images/f3016.png" alt="" />
|
|
|
<li>残差平方和:又称误差平方和,反映除x 以外的其他因素对y 取值的影响,也称为不可解释的平方和或剩余平方和。</li>
|
|
|
<img src="@/assets/images/f3017.png" alt="" />
|
|
|
<li>回归平方和(SSR):反映自变量x 的变化对因变量y 取值变化的影响,或者说,是由于x 与y 之间的线性关系引起的y 的取值变化,也称为可解释的平方和。</li>
|
|
|
<img src="@/assets/images/f3018.png" alt="" />
|
|
|
<li>三者的关系为:</li>
|
|
|
<img src="@/assets/images/f3019.png" alt="" />
|
|
|
<li>
|
|
|
估计标准误差(s
|
|
|
<sub>e</sub>
|
|
|
):反映实际观察值在回归直线周围的分散状况,是均方残差(MSE)的平方根
|
|
|
</li>
|
|
|
<img src="@/assets/images/f3020.png" alt="" />
|
|
|
<p style="font-size: 19px; font-weight: 600">显著性检验</p>
|
|
|
<img src="@/assets/images/f3021.png" alt="" />
|
|
|
<img src="@/assets/images/f3022.png" alt="" />
|
|
|
<p style="font-size: 19px; font-weight: 600">利用回归方程进行预测</p>
|
|
|
<p style="font-size: 16px; font-weight: 600">平均值的置信区间</p>
|
|
|
<li>
|
|
|
置信区间(confidence interval):利用估计的回归方程,对于自变量x 的一个给定值x
|
|
|
<sub>0</sub>
|
|
|
,求出因变量y yy的平均值的估计区间,这一估计区间称为置信区间。
|
|
|
</li>
|
|
|
<p>比平均值的公式根号内多了个1而已:</p>
|
|
|
<img src="@/assets/images/f3023.png" alt="" style="width: 600px;"/>
|
|
|
<p style="font-size: 19px; font-weight: 600">残差分析</p>
|
|
|
<p style="font-size: 16px; font-weight: 600">残差与残差图(检验方差齐性)</p>
|
|
|
<li>残差:因变量的观测值与根据估计的回归方程求出的预测值之差,用e表示,反映了用估计的回归方程去预测而引起的误差。</li>
|
|
|
<img src="@/assets/images/f3024.png" alt="" /><br />
|
|
|
<img src="@/assets/images/f3025.png" alt="" style="width: 600px;height: 400px;"/>
|
|
|
<p style="font-size: 19px; font-weight: 600">标准化残差(检验正态性)</p>
|
|
|
<li>标准化残差:也称为Pearson 残差或半学生化残差(semistudentized residuals)。</li>
|
|
|
<img src="@/assets/images/f3026.png" alt="" />
|
|
|
</div>
|
|
|
</template>
|
|
|
</pop-model>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
import * as portraitModel from "@/api/portraitModel";
|
|
|
|
|
|
import popModel from "@/views/components/popModal.vue";
|
|
|
import * as echarts from "echarts";
|
|
|
import * as API from "@/api/AI.js";
|
|
|
import { getUserInfo } from "@/utils/auth";
|
|
|
import * as XLSX from "XLSX";
|
|
|
import { onMounted, reactive } from "vue";
|
|
|
const { proxy } = getCurrentInstance();
|
|
|
const dialogVisible = ref(false);
|
|
|
const formInline3 = reactive({
|
|
|
value1: "",
|
|
|
value2: "",
|
|
|
value3: "",
|
|
|
});
|
|
|
const loading1 = ref(false);
|
|
|
const task = () => {
|
|
|
let errorNumber=0
|
|
|
for (let key in formInline3) {
|
|
|
if (formInline3[key] == "") {
|
|
|
proxy.$modal.msgWarning("请填写完整!");
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
if(input4.value==="线性回归"){
|
|
|
if(formInline3.value1!==tableData3.value[0].intercept.toString()){
|
|
|
errorNumber=1
|
|
|
}
|
|
|
if(formInline3.value2!==tableData3.value[0].slopes){
|
|
|
errorNumber=1
|
|
|
}
|
|
|
if(parseFloat(formInline3.value3)!==parseFloat(predictionResults.value)){
|
|
|
errorNumber=1
|
|
|
}
|
|
|
}else if(input4.value==="Logistic逻辑回归"){
|
|
|
if(parseFloat(formInline3.value1)!==parseFloat(tableData3.value[0].intercept)){
|
|
|
errorNumber=1
|
|
|
}
|
|
|
if(parseFloat(formInline3.value2)!==parseFloat(tableData3.value[0].slope)){
|
|
|
errorNumber=1
|
|
|
}
|
|
|
if(parseFloat(formInline3.value3)!==parseFloat(predictionResults.value)){
|
|
|
errorNumber=1
|
|
|
}
|
|
|
}else{
|
|
|
errorNumber=1
|
|
|
}
|
|
|
portraitModel
|
|
|
.submit({
|
|
|
userId: JSON.parse(getUserInfo()).userId,
|
|
|
taskName: "回归分析",
|
|
|
numberOfErrors: errorNumber,
|
|
|
})
|
|
|
.then((res) => {
|
|
|
dialogVisible.value = false;
|
|
|
proxy.$modal.msgSuccess("提交完成!");
|
|
|
});
|
|
|
};
|
|
|
const dialogVisible2 = ref(false);
|
|
|
const flagColumn = ref(false);
|
|
|
const runResultShow = ref(false);
|
|
|
const exportTableRef = ref(null);
|
|
|
const tableLabel = reactive([{ prop: "date", label: "" }]);
|
|
|
const tableLabel2 = reactive([{ prop: "date", label: "" }]);
|
|
|
const formInline2 = reactive({
|
|
|
user: "",
|
|
|
});
|
|
|
const flagUP = ref(false);
|
|
|
const option5 = ref([]);
|
|
|
const option6 = ref([]);
|
|
|
const getList = () => {
|
|
|
API.selectionMetrics({ userId: JSON.parse(getUserInfo()).userId }).then((res) => {
|
|
|
res.data.forEach((element) => {
|
|
|
options.value.push({
|
|
|
value: element,
|
|
|
label: element,
|
|
|
});
|
|
|
});
|
|
|
});
|
|
|
};
|
|
|
const showChart = ref(false);
|
|
|
const fileList = ref([]);
|
|
|
const handleChange = (info) => {
|
|
|
fileList.value.push(info);
|
|
|
};
|
|
|
const flag = ref(false);
|
|
|
|
|
|
onMounted(() => {
|
|
|
getList();
|
|
|
});
|
|
|
|
|
|
const optionData = () => {
|
|
|
API.viewingMetrics({ userId: JSON.parse(getUserInfo()).userId, tableName: input.value, algorithmName: "回归分析" }).then((res) => {
|
|
|
tableData.value = [];
|
|
|
input5.value=[]
|
|
|
input6.value=[]
|
|
|
input3.value=""
|
|
|
res.data.forEach((element) => {
|
|
|
tableData.value.push({
|
|
|
text: element,
|
|
|
});
|
|
|
});
|
|
|
});
|
|
|
};
|
|
|
const selectedRows = ref([]);
|
|
|
const handleSelectionChange = (selection) => {
|
|
|
selectedRows.value = selection;
|
|
|
};
|
|
|
const tableData2 = ref([]);
|
|
|
const tableData3 = ref([]);
|
|
|
const scrollbar = ref(null);
|
|
|
const resTable2 = ref();
|
|
|
const taskZB = () => {
|
|
|
flag.value = true;
|
|
|
if (selectedRows.value.length === 0) {
|
|
|
return proxy.$modal.msgWarning("请选择指标!");
|
|
|
}
|
|
|
const sendData = {
|
|
|
tableName: input.value,
|
|
|
userId: JSON.parse(getUserInfo()).userId,
|
|
|
fieldList: selectedRows.value.map((item) => item.text),
|
|
|
};
|
|
|
API.analysisDataDisplay(sendData).then((res) => {
|
|
|
tableLabel.length = 0;
|
|
|
option5.value.length = 0;
|
|
|
for (const key in res.data[0]) {
|
|
|
option5.value.push({
|
|
|
value: key,
|
|
|
label: key,
|
|
|
});
|
|
|
tableLabel.push({
|
|
|
label: key,
|
|
|
prop: key,
|
|
|
});
|
|
|
}
|
|
|
tableData2.value = res.data;
|
|
|
flag.value = true;
|
|
|
});
|
|
|
};
|
|
|
const formInline = reactive({
|
|
|
user: "",
|
|
|
region: "",
|
|
|
});
|
|
|
const input = ref();
|
|
|
const options = ref([]);
|
|
|
const input2 = ref("");
|
|
|
const options2 = ref([
|
|
|
{
|
|
|
value: "数据区重",
|
|
|
label: "数据去重",
|
|
|
},
|
|
|
]);
|
|
|
const input3 = ref("");
|
|
|
const options3 = ref([
|
|
|
{
|
|
|
value: "缺失值处理--剔除数据",
|
|
|
label: "缺失值处理--剔除数据",
|
|
|
},
|
|
|
{
|
|
|
value: "缺失值处理--均值替换",
|
|
|
label: "缺失值处理--均值替换",
|
|
|
},
|
|
|
]);
|
|
|
const input4 = ref();
|
|
|
const options4 = ref([
|
|
|
{
|
|
|
value: "Logistic逻辑回归",
|
|
|
label: "线性回归",
|
|
|
},
|
|
|
]);
|
|
|
const input5 = ref();
|
|
|
const input6 = ref();
|
|
|
const taskSubmit = () => {
|
|
|
dialogVisible.value = true;
|
|
|
};
|
|
|
const tableData = ref([]);
|
|
|
const headerCellStyle = () => {
|
|
|
return {
|
|
|
backgroundColor: "#1882DE !important", // 设置表头背景颜色
|
|
|
color: "#ffffff !important",
|
|
|
};
|
|
|
};
|
|
|
const optionData2 = () => {
|
|
|
if (tableData2.value.length === 0) {
|
|
|
input2.value = "";
|
|
|
input3.value = "";
|
|
|
proxy.$modal.msgWarning("请先选择指标!");
|
|
|
return;
|
|
|
}
|
|
|
if (input2.value && input3.value) {
|
|
|
const sendData = ref({
|
|
|
mapList: tableData2.value,
|
|
|
method: input3.value,
|
|
|
userId: JSON.parse(getUserInfo()).userId,
|
|
|
});
|
|
|
API.dataPreprocessing(sendData.value).then((res) => {
|
|
|
resTable2.value = res.data;
|
|
|
tableData2.value = [];
|
|
|
tableData2.value = res.data;
|
|
|
proxy.$modal.msgSuccess("预处理成功!");
|
|
|
});
|
|
|
}
|
|
|
};
|
|
|
//生产表格
|
|
|
const computation = () => {
|
|
|
if (tableData.value.length === 0 || input2.value == "" || input3.value == "") {
|
|
|
proxy.$modal.msgWarning("请先计算/对数据进行预处理!");
|
|
|
return;
|
|
|
}
|
|
|
if (input5.value && input6.value && input4.value) {
|
|
|
let sendData = {
|
|
|
y: [],
|
|
|
x: [],
|
|
|
userId: JSON.parse(getUserInfo()).userId,
|
|
|
};
|
|
|
loading1.value = true;
|
|
|
if (input4.value === "线性回归") {
|
|
|
if (input5.value.length > 1) {
|
|
|
proxy.$modal.msgError("y变量数量有误!");
|
|
|
return;
|
|
|
}
|
|
|
if (input6.value.length != 2 || input6.value.length > 2) {
|
|
|
proxy.$modal.msgError("x变量数量有误!");
|
|
|
return;
|
|
|
}
|
|
|
flagColumn.value = true;
|
|
|
tableData2.value.forEach((item) => {
|
|
|
sendData.y.push(item[input5.value[0]]);
|
|
|
sendData.x.push([item[input6.value[0]], item[input6.value[1]]]);
|
|
|
});
|
|
|
API.linearRegression(sendData).then((res) => {
|
|
|
tableLabel2.length = 0;
|
|
|
for (const key in res.data) {
|
|
|
tableLabel2.push({
|
|
|
label: key,
|
|
|
prop: key,
|
|
|
});
|
|
|
}
|
|
|
let data = res.data;
|
|
|
data.slopes = data.slopes.join(",");
|
|
|
tableData3.value = [data];
|
|
|
predictionResults.value = "";
|
|
|
loading1.value = false;
|
|
|
});
|
|
|
} else {
|
|
|
if (input5.value.length > 1) {
|
|
|
proxy.$modal.msgError("y变量数量有误!");
|
|
|
return;
|
|
|
}
|
|
|
if (input6.value.length > 1) {
|
|
|
proxy.$modal.msgError("x变量数量有误!");
|
|
|
return;
|
|
|
}
|
|
|
flagColumn.value = true;
|
|
|
if (input6.value.length === 1) {
|
|
|
tableData2.value.forEach((item) => {
|
|
|
sendData.y.push(item[input5.value[0]]);
|
|
|
sendData.x.push(item[input6.value[0]]);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
API.logisticRegression(sendData).then((res) => {
|
|
|
tableLabel2.length = 0;
|
|
|
for (const key in res.data) {
|
|
|
tableLabel2.push({
|
|
|
label: key,
|
|
|
prop: key,
|
|
|
});
|
|
|
}
|
|
|
let data = res.data;
|
|
|
data.slope = data.slope;
|
|
|
tableData3.value = [data];
|
|
|
predictionResults.value = "";
|
|
|
loading1.value = true;
|
|
|
});
|
|
|
}
|
|
|
} else {
|
|
|
proxy.$modal.msgWarning("请模型参数进行设置!");
|
|
|
}
|
|
|
nextTick(() => {
|
|
|
setTimeout(() => {
|
|
|
loading1.value = false;
|
|
|
const scrollContainer = scrollbar.value?.$el.querySelector(".el-scrollbar__wrap");
|
|
|
if (scrollContainer) {
|
|
|
scrollContainer.scrollTo({
|
|
|
top: scrollContainer.scrollHeight,
|
|
|
behavior: "smooth", // 平滑滚动
|
|
|
});
|
|
|
}
|
|
|
}, 500);
|
|
|
});
|
|
|
flagUP.value = true;
|
|
|
};
|
|
|
const nowData = ref([]);
|
|
|
const handleClick = (item) => {
|
|
|
dialogVisible2.value = true;
|
|
|
nowData.value = item;
|
|
|
};
|
|
|
const predictionResults = ref("");
|
|
|
const Forecasting = () => {
|
|
|
// if (nowData.value.type === "线性回归") {
|
|
|
// const sendData = {
|
|
|
// intercept: nowData.value.intercept,
|
|
|
// type: nowData.value.type,
|
|
|
// slopes: nowData.value.slopes.split(",").map(Number),
|
|
|
// raX: formInline2.user.split(",").map(Number),
|
|
|
// };
|
|
|
// API.logisticRegressionPrediction(sendData).then((res) => {
|
|
|
// dialogVisible2.value = false;
|
|
|
// predictionResults.value = res.data;
|
|
|
// });
|
|
|
// }
|
|
|
// if (nowData.value.type === "逻辑回归") {
|
|
|
const sendData = {
|
|
|
intercept: nowData.value.intercept,
|
|
|
slope: nowData.value.slope,
|
|
|
x: formInline2.user,
|
|
|
};
|
|
|
API.logisticRegressionPrediction(sendData).then((res) => {
|
|
|
dialogVisible2.value = false;
|
|
|
predictionResults.value = res.data;
|
|
|
});
|
|
|
// }
|
|
|
};
|
|
|
const upLoad = () => {
|
|
|
const tableDom = exportTableRef.value?.$el;
|
|
|
if (!tableDom) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
const wb = XLSX.utils.table_to_book(tableDom);
|
|
|
XLSX.writeFile(wb, "回归分析.xlsx");
|
|
|
};
|
|
|
const startOver = () => {
|
|
|
input.value = "";
|
|
|
tableData.value = [];
|
|
|
tableData2.value = [];
|
|
|
tableData3.value = [];
|
|
|
input2.value = "";
|
|
|
input3.value = "";
|
|
|
input4.value = "";
|
|
|
input5.value = [];
|
|
|
input6.value = [];
|
|
|
flagColumn.value = false;
|
|
|
tableLabel.length = 0;
|
|
|
tableLabel2.length = 0;
|
|
|
nowData.value = [];
|
|
|
formInline2.user = "";
|
|
|
predictionResults.value = "";
|
|
|
flagUP.value = false;
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
.main-top {
|
|
|
margin: 20px 20px 0;
|
|
|
margin-top: 10px;
|
|
|
height: 85px;
|
|
|
background: #001d40;
|
|
|
border: 1px solid #0452c6;
|
|
|
padding: 5px 20px;
|
|
|
}
|
|
|
.app-main {
|
|
|
// background-color: #f5f5f5;
|
|
|
// min-height: 965px;
|
|
|
margin: 0px 20px 0;
|
|
|
// height: 100%;
|
|
|
display: flex;
|
|
|
overflow: auto;
|
|
|
.main-left {
|
|
|
//水平居中
|
|
|
flex-direction: column;
|
|
|
// min-height: 965px;
|
|
|
display: flex;
|
|
|
width: 205px;
|
|
|
height: 100%;
|
|
|
background: #041c49;
|
|
|
// padding: 0px 10px;
|
|
|
.left-top {
|
|
|
padding: 10px;
|
|
|
span {
|
|
|
font-weight: bold;
|
|
|
font-size: 18px;
|
|
|
color: #3596eb;
|
|
|
}
|
|
|
}
|
|
|
.metrics-table {
|
|
|
.el-button {
|
|
|
width: 149px;
|
|
|
height: 48px;
|
|
|
background: url("../../../assets/images/确定.png");
|
|
|
color: #ffffff;
|
|
|
border-color: #ffffff00;
|
|
|
background-size: 100% 100%;
|
|
|
margin: 15px;
|
|
|
}
|
|
|
.el-input {
|
|
|
--el-input-text-color: #ffffff;
|
|
|
--el-input-bg-color: #002651;
|
|
|
--el-input-border-color: #67b3d6;
|
|
|
}
|
|
|
}
|
|
|
.startOver {
|
|
|
width: 150px;
|
|
|
height: 40px;
|
|
|
background: #00f4ff;
|
|
|
margin: auto;
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
cursor: pointer;
|
|
|
}
|
|
|
:deep(.el-table) {
|
|
|
--el-table-row-hover-bg-color: #002651 !important;
|
|
|
--el-table-border-color: #7ac1ff;
|
|
|
.el-table__row {
|
|
|
background-color: #002652 !important;
|
|
|
color: #e6e6e6;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
.main-right {
|
|
|
width: 1639px;
|
|
|
// height: 100%;
|
|
|
// padding: 20px;
|
|
|
border: 1px solid #0452c6;
|
|
|
:deep(.el-table__header) {
|
|
|
.el-table__cell {
|
|
|
background: linear-gradient(0deg, #5304be 0%, #9126fe 100%) !important;
|
|
|
}
|
|
|
}
|
|
|
:deep(.el-table) {
|
|
|
--el-table-row-hover-bg-color: #002651 !important;
|
|
|
--el-table-border-color: #002651;
|
|
|
--el-table-bg-color: #ffffff00;
|
|
|
.el-table__row {
|
|
|
background-color: #002652 !important;
|
|
|
color: #e6e6e6;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
.metrics {
|
|
|
:deep(.el-input) {
|
|
|
.el-input__wrapper {
|
|
|
background-color: #ffffff00;
|
|
|
background-image: url("../../../assets/images/下拉框.png");
|
|
|
background-size: 100% 100%;
|
|
|
}
|
|
|
--el-input-text-color: #ffffff;
|
|
|
--el-input-border-color: #ffffff00;
|
|
|
--el-input-hover-border-color: #ffffff00;
|
|
|
--el-input-hover-border: #ffffff00;
|
|
|
--el-select-border-color-hover: #ffffff00;
|
|
|
--el-select-input-focus-border-color: #ffffff00;
|
|
|
--el-input-placeholder-color: #ffffff;
|
|
|
.el-input__inner {
|
|
|
color: #ffffff;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
.metrics2 {
|
|
|
:deep(.el-input) {
|
|
|
.el-input__wrapper {
|
|
|
background-color: #ffffff00;
|
|
|
}
|
|
|
--el-input-text-color: #ffffff;
|
|
|
--el-input-border-color: #409eff;
|
|
|
--el-input-hover-border-color: #409eff;
|
|
|
--el-input-hover-border: #409eff;
|
|
|
--el-select-border-color-hover: #409eff;
|
|
|
--el-select-input-focus-border-color: #409eff;
|
|
|
--el-input-placeholder-color: #ffffff;
|
|
|
.el-input__inner {
|
|
|
color: #ffffff;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
.analysisResults {
|
|
|
.imgBtn {
|
|
|
width: 89px;
|
|
|
height: 31px;
|
|
|
background: url("../../../assets/images/下载.png");
|
|
|
color: black;
|
|
|
border-color: #ffffff00;
|
|
|
// background-size: 100% 100%;
|
|
|
margin: 15px 0px 5px;
|
|
|
}
|
|
|
}
|
|
|
:deep(.el-form-item__label) {
|
|
|
color: #ffffff;
|
|
|
}
|
|
|
.from-item {
|
|
|
padding: 20px;
|
|
|
.el-input {
|
|
|
--el-input-text-color: #ffffff;
|
|
|
--el-input-bg-color: #002651;
|
|
|
--el-input-border-color: #67b3d6;
|
|
|
}
|
|
|
}
|
|
|
.dialog-footer {
|
|
|
margin-bottom: 20px;
|
|
|
}
|
|
|
:deep(.el-table__expand-icon) {
|
|
|
color: #9126fe;
|
|
|
.el-icon {
|
|
|
font-size: 16px;
|
|
|
}
|
|
|
}
|
|
|
</style>
|