spc x-bar 正态分布 echarts demo

使用echarts,elementUi,vue编写的spc分析的demo示例.

含x-bar和正态分布图,同一数据可以互转

在这里插入图片描述
在这里插入图片描述

chart.vue

<template><div class="app-container"><el-row><el-col :span="4" class="button-container"><el-button @click="redrawChart">重新绘制</el-button><el-button type="warning" @click="analyzeData">重新解析数据并绘制</el-button><el-button type="primary" @click="drawNormalChart">正态分布(X)</el-button><el-button type="success" @click="showSpecDialog">更新SPEC(X)</el-button><el-button type="info">计算cpk(X)</el-button><el-button type="danger">危险按钮(X)</el-button></el-col><el-col :span="20"><div id="mainChart" style="height: 720px;width: 1080px;"/></el-col></el-row><div>min:{{ dData.min.toFixed(3) }}max:{{ dData.min.toFixed(3) }}mean:{{ dData.min.toFixed(3) }}std:{{ dData.min.toFixed(3) }}</div><div>说明1.x-bar等图的上线边界,计算上下边界,如果数据过于集中,自动图表缩放会导致usl甚至是ucl超出y轴范围,不能正常绘制,那么需要手动计算上下边界<br/>上边界取max值和usl+0.5*(usl-ucl)更大的那个<br/>下边界取min值和lsl-0.5*(lcl-lsl)更小的那个<br/>为避免出现小数位数过多/精度不足 取3位小数<br/>2.关闭SPEC弹框时由于数据已经被更新,所以在关闭弹框时间上直接绑定了重绘事件.但是由于上下边界是在解析数据阶段完成的,所以不会重新解析上下边界</div><el-dialog title="更新SPEC" :visible.sync="visibleSpecDialog" width="800px" top="5vh" @closed="onSpecDialogClose" append-to-body><el-form ref="form" :model="dData" label-width="200px"><el-form-item label="usl"><el-input v-model="dData.usl"/></el-form-item><el-form-item label="ucl"><el-input v-model="dData.ucl"/></el-form-item><el-form-item label="lcl"><el-input v-model="dData.lcl"/></el-form-item><el-form-item label="lsl"><el-input v-model="dData.lsl"/></el-form-item></el-form></el-dialog></div>
</template><script>
import * as echarts from "echarts";
import * as utils from './utils';//定义显示的颜色
let red="#FF0000"
let yellow="#CCCC00"
let green="#009000"export default {data() {//参数定义return {//主chart实例对象mainChart: {},//从服务器查询数据参数对象queryParams: {},//从服务器获取的原始数据(originalData)oData: {usl: 0,ucl: 0,cl: 0,lcl: 0,lsl: 0,dataList: []},//预定义维度数组,注意顺序,不要轻易改变,注意需要调整analyzeData的转二维数组的内容columns: ["dataTime", "paramValue", "remark"],//绘制图需要的数据格式,(drawData)dData: {//控制参数usl: 0,ucl: 0,cl: 0,lcl: 0,lsl: 0,//计算参数min: 0,max: 0,mean: 0,std: 0,upperY: 0,lowerY: 0,//仅提取paramValue作为值数组valueData: [],//x-barData 数据格式,就是二维数组xBarData: [],//正态分布数据格式normalData: {//正态分布前后距离dataRangeMinOP: 1,dataRangeMaxOP: 1.1,//组间距interval: 1,// 这3个就不构建datasource来处理了,直接用好了// 构建离散值x轴xAxis: [],// 构建柱状y轴barYaxis: [],// 构建线性y轴lineYaxis: []}},// 当前图表类型 1.XR 2.XS 3.WR 4.ZT FIXMEshowChartType: 1,//显示更新SPEC弹框标记visibleSpecDialog: false};},mounted() {this.init();},methods: {/*** 初始化方法* 调用过程如下:* init->queryData->analyzeData->redrawChart->createOption->this.chart.setOption*/init() {//从dom加载echarts对象let chartDom = document.getElementById("mainChart");this.chart = echarts.init(chartDom);this.queryData();},/*** 从服务器获取原始数据* 实际参数:this.queryParams.... 返回结果到this.oData* 回调触发redrawChart*/queryData() {this.oData.dataList = []//模拟写入数据for (let n = 0; n < 100; n++) {this.oData.dataList.push({dataTime: n + ":00",paramValue: 30 + Math.random() * 30,remark: (Math.random() * 20).toFixed(3)});}this.oData.usl = 55;this.oData.ucl = 50;this.oData.cl = 45;this.oData.lcl = 40;this.oData.lsl = 35;//解析原始为图表需要的数据this.analyzeData();},/*** 绘制,或重新绘制主chart图*/redrawChart() {//清除图表this.chart.clear()//创建option并绘制let option = this.createOption();this.chart.setOption(option);//弹框说明this.$message.success("绘制图表成功!");},drawNormalChart() {if (this.showChartType === 1) {this.showChartType = 4;} else {this.showChartType = 1;}this.redrawChart();},showSpecDialog() {this.visibleSpecDialog = true;},//Spec弹框被关闭onSpecDialogClose() {this.redrawChart();},/*** 将原始数据解析为x-bar等图需要的格式* 计算mean,std.,cpk..等数据返回* 实际参数:this.oData.... 返回结果到this.dData*/analyzeData() {//copy基础数据this.dData.usl = this.oData.usl;this.dData.ucl = this.oData.ucl;this.dData.cl = this.oData.cl;this.dData.lcl = this.oData.lcl;this.dData.lsl = this.oData.lsl;//仅提取paramValue作为值数组this.dData.valueData = this.oData.dataList.map(obj => obj.paramValue);//计算其他数据,最大最小cpk什么的this.dData.min = Math.min(...this.dData.valueData);this.dData.max = Math.max(...this.dData.valueData);this.dData.mean = this.dData.valueData.reduce((sum, val) => sum + val, 0) / this.dData.valueData.length;this.dData.std = utils.getStd(this.dData.valueData, this.dData.mean)//计算上下边界,如果数据过于集中,自动图表缩放会导致usl甚至是ucl超出y轴范围,不能正常绘制,那么需要手动计算上下边界//取max值和usl+0.5*(usl-ucl)更大的那个//取min值和lsl-0.5*(lcl-lsl)更小的那个this.dData.upperY = Math.max(this.dData.usl + 0.5 * (this.dData.usl - this.dData.ucl), this.dData.max).toFixed(3)this.dData.lowerY = Math.min(this.dData.lsl - 0.5 * (this.dData.lcl - this.dData.lsl), this.dData.min).toFixed(3)// 转x-bar需要数据// 对象数组转二维数组this.dData.xBarData = []this.dData.xBarData = this.oData.dataList.map(obj => [obj.dataTime, obj.paramValue, obj.remark]);// 转正态分布数据// 构建x轴let start = this.dData.min - this.dData.normalData.dataRangeMinOP;let end = this.dData.max + this.dData.normalData.dataRangeMaxOP;// 计算区间数量let numIntervals = Math.ceil((end - start) / this.dData.normalData.interval);// 构建离散值x轴let xAxis = [];for (let i = start; i <= end; i = i + this.dData.normalData.interval) {let str = i.toFixed(1).toString();xAxis.push(str);}this.dData.normalData.xAxis = xAxis;// 构建柱状y轴,遍历数组并计算频数let barYaxis = new Array(numIntervals).fill(0);this.dData.valueData.forEach((value) => {if (value >= start && value <= end) {// 找到值所在的区间let intervalIndex = Math.floor((value - start) / this.dData.normalData.interval);// 增加该区间的频数barYaxis[intervalIndex]++;}});this.dData.normalData.barYaxis = barYaxis;// 构建线性y轴this.dData.normalData.lineYaxis = utils.fxNormalDistribution(xAxis, this.dData.std, this.dData.mean);this.redrawChart();},/*** 构建图图表参数* @returns*/createOption() {//内部匿名方法无法访问到this,用这个处理,下面都采用thatlet that = this;//optionlet option = {};//正态分布if (this.showChartType === 4) {//定义实际数据的频数柱状图let barDataSet = {type: "bar",smooth: true,yAxisIndex: 0,areaStyle: {opacity: 0,},data: that.dData.normalData.barYaxis,name: "实际分布频数",label: {formatter: "{c} %",show: false, //默认显示position: "top", //在上方显示textStyle: {//数值样式fontSize: 16,},},};//计算实际数据的正态分布图let lineDataSet = {type: "line",smooth: true,yAxisIndex: 1,areaStyle: {opacity: 0,},data: that.dData.normalData.lineYaxis,name: "实际正态分布",label: {formatter: "{c} %",show: false, //开启显示position: "top", //在上方显示textStyle: {//数值样式fontSize: 16,},},};option = {title: {text: 'SPC',},//提示框组件tooltip: {trigger: "axis",axisPointer: {type: "shadow",},},xAxis: {boundaryGap: true,type: "category",data: that.dData.normalData.xAxis,},//定义y轴yAxis: [{type: "value",}, {type: "value",}],series: [barDataSet, lineDataSet],};}//x-barelse {option = {title: {text: 'SPC',},tooltip: {trigger: 'axis',//轴数据指示axisPointer: {type: 'cross'},},xAxis: {type: 'category'},yAxis: {type: 'value',max: that.dData.upperY,min: that.dData.lowerY},dataset: [{//定义数据字段dimensions: [{name: "dataTime", type: 'ordinal'}, "paramValue", "remark"],//定义数据内容source: that.dData.xBarData},],series: [{name: 'Dow-Jones index',type: 'line',//密集点数过多是否显示showAllSymbol: true,//定义xy轴取数据那一列值encode: {x: 'dataTime',y: 'paramValue',tooltip: ["paramValue", "dataTime", "remark"],},//定义点样式,依据数据定义点样式以及大小颜色symbol: function (params) {if (params[1] > that.dData.ucl || params[1] < that.dData.lcl) {if (params[1] > that.dData.usl || params[1] < that.dData.lsl) {return 'triangle';}return 'circle';} else {return 'emptyCircle';}},symbolSize: function (params) {if (params[1] > that.dData.ucl || params[1] < that.dData.lcl) {if (params[1] > that.dData.usl || params[1] < that.dData.lsl) {return 10;}return 9;} else {return 8;}},itemStyle: {color: function (params) {if (params.data[1] > that.dData.ucl || params.data[1]< that.dData.lcl) {if (params.data[1] > that.dData.usl || params.data[1] < that.dData.lsl) {return red;}return yellow;} else {return green;}}},//定义规格线markLine: {silent: true,symbol: 'none',data: [{name: 'USL',yAxis: that.dData.usl,lineStyle: {color: red},label: {color: red, formatter: 'USL:' + that.dData.usl, fontSize: 10}},{name: 'UCL',yAxis: that.dData.ucl,lineStyle: {color: yellow},label: {color: yellow, formatter: 'UCL:' + that.dData.ucl, fontSize: 10}},{name: 'CL',yAxis: that.dData.cl,lineStyle: {color: green},label: {color: green, formatter: 'CL:' + that.dData.cl, fontSize: 10}},{name: 'LCL',yAxis: that.dData.lcl,lineStyle: {color: yellow},label: {color: yellow, formatter: 'LCL:' + that.dData.lcl, fontSize: 10}},{name: 'LSL',yAxis: that.dData.lsl,lineStyle: {color: red},label: {color: red, formatter: 'LSL:' + that.dData.lsl, fontSize: 10}}]}}]};}return option;}},};
</script><style scoped>
.button-container {display: grid;grid-template-columns: 1fr; /* 单列 */grid-auto-rows: minmax(auto, auto); /* 自动行高 */row-gap: 10px; /* 行间距 *//* 可以根据需要添加更多样式 */
}.button-container .el-button {margin-right: 10px;margin-left: 10px;
}
</style>

utils.js

//计算正态曲线
export function fxNormalDistribution(array, std, mean) {let valueList = [];for (let i = 0; i < array.length; i++) {let ND =Math.sqrt(2 * Math.PI) *std *Math.pow(Math.E,-(Math.pow(array[i] - mean, 2) / (2 * Math.pow(std, 2))));valueList.push(ND.toFixed(3));}return valueList;
}//计算标准差
export function getStd(data, mean) {let sumXY = function (x, y) {return Number(x) + Number(y);};let square = function (x) {return Number(x) * Number(x);};let deviations = data.map(function (x) {return x - mean;});return Math.sqrt(deviations.map(square).reduce(sumXY) / (data.length - 1));
}//对有序数组求中位数
export function getMedianSorted(arr) {// 获取数组长度let len = arr.length;// 如果没有元素,返回undefined或你可以返回其他合适的值if (len === 0) {return undefined;}// 如果只有一个元素,那么它就是中位数if (len === 1) {return arr[0];}// 如果数组长度是奇数,返回中间的数if (len % 2 === 1) {return arr[Math.floor(len / 2)];}// 如果数组长度是偶数,返回中间两个数的平均值else {let mid1 = arr[len / 2 - 1];let mid2 = arr[len / 2];return (mid1 + mid2) / 2.0;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/746487.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【vue项目中点击下载】弹窗提示:离开此网站?系统可能不会保存您所做的更改,改为直接下载,不提示此弹窗内容,已解决

项目中用的是window.location.href实现下载 在Web浏览器中&#xff0c;当尝试通过window.location.href重定向到一个文件下载URL时&#xff0c;浏览器通常会显示一个确认对话框&#xff0c;询问用户是否要离开当前页面&#xff0c;因为下载的文件通常是在新窗口或新标签页中打…

程序员如何平衡主业与副业?

程序员的副业有哪些&#xff1f; 常见的有接私活&#xff0c;即外包一些软件项目来做&#xff0c;或者是写文章、拍教学视频、开直播等等。在这里&#xff0c;我更推荐程序员的副业是找个软件开发外包平台来接单&#xff0c;就是在工作之外接一下软件开发、外包项目等&#xf…

软件无线电系列——模拟无线电、数字无线电、软件无线电

本节目录 一、模拟无线电 二、数字无线电 1、窄带数字无线电 2、宽带数字无线电 三、软件无线电本节内容 一、模拟无线电 20世纪80年代的模拟体制(美国的AMPS/欧洲的TACS)被称为第一代移动通信&#xff0c;简称1G,主要目标是为在大范围内有限的用户提供移动电话服务。最主要的…

[Django 0-1] Core.Handlers 模块

Core.Handlers 模块 这个模块封装了 wsgi,asgi 两个类&#xff0c;分别用于处理外部的请求信息&#xff0c;asgi 提供异步处理能力。 Handler 模块将请求Request封装包裹了Middleware中间件&#xff0c;并将处理结果返回为Response响应对象。 BaseHandler 重要函数 load_m…

buuctf 部分web题

[b01lers2020]Welcome to Earth 打开网站&#xff0c;停一会会跳转die&#xff0c;了解一下&#xff0c;这就类似一个通关游戏&#xff0c;不能死亡&#xff0c;也就是说进入/die这个网站就意味着题就做不出来了&#xff1b;所以回到上一个网站原网站&#xff0c;查看源码&…

神经网络量化

神经网络量化&#xff08;Neural Network Quantization&#xff09;是一种技术&#xff0c;旨在减少神经网络模型的计算和存储资源需求&#xff0c;同时保持其性能。在深度学习中&#xff0c;神经网络模型通常使用高精度的参数&#xff08;例如32位浮点数&#xff09;来表示权重…

如何关闭 Visual Studio 双击异常高亮

[问题描述]&#xff1a; 最近 Visual Studio 更新后&#xff0c;双击选中关键字快要亮瞎我的眼睛了 &#x1f440;&#x1f440; [解决方法]&#xff1a; 摸索了一下&#xff0c;找到了关闭的方法&#xff1a;工具 → 选项 → 文本编辑器 → 常规&#xff0c;然后取消 勾选 sel…

红帽认证含金量如何?红帽rhcsa认证证书认可度高吗?

事实上&#xff0c;红帽认证含金量在全球范围内都得到了广泛的认可和重视。许多企业和组织都将红帽认证作为招聘和选拔人才的重要标准之一。持有红帽认证的个人往往能够获得更好的职业机会和更高的薪资水平。此外&#xff0c;红帽认证还被许多政府机构、行业协会和教育机构所认…

888888888888888888后果聚光镜

☞ 通用计算机启动过程 1️⃣一个基础固件&#xff1a;BIOS 一个基础固件&#xff1a;BIOS→基本IO系统&#xff0c;它提供以下功能&#xff1a; 上电后自检功能 Power-On Self-Test&#xff0c;即POST&#xff1a;上电后&#xff0c;识别硬件配置并对其进行自检&#xff0c…

html行内元素(内联元素),块级元素分别有哪些?

html行内元素&#xff08;内联元素&#xff09;&#xff0c;块级元素分别有哪些&#xff1f; 常用的分类包括行内元素&#xff08;内联元素&#xff09;和块级元素。下面是它们的示例列表&#xff1a; 行内元素&#xff08;Inline Elements&#xff09;&#xff1a; <span&…

laravel 表单验证的 exists、unique 去除软删除字段的校验

use Illuminate\Validation\Rule; exists 去除软删除字段的校验 $validator \Validator::make($data, [phone_new > [Rule::exists(users, phone)->whereNull(deleted_at),]], [phone_new.exists > 手机号不存在,]);unique 去除软删除字段的校验 // 新增 email>r…

vue3动态组件未渲染问题

渲染问题 component动态组件写法与vue2写法一致&#xff0c;代码如下&#xff1a; <component :is"componentName"/><script setup>import { ref } from vueimport account from ./user/account.vue// 组件名称const componentName ref(account)// 点击…

【算法】一类支持向量机OC-SVM(1)

【算法】一类支持向量机OC-SVM 前言一类支持向量机OC-SVM 概念介绍示例编写数据集创建实现一类支持向量机OC-SVM完整的示例输出 前言 由于之前毕设期间主要的工具就是支持向量机&#xff0c;从基础的回归和分类到后来的优化&#xff0c;在接触到支持向量机还有一类支持向量机的…

unity

Unity官方下载_Unity最新版_从Unity Hub下载安装 | Unity中国官网 Unity Remote - Unity 手册 登陆账号&#xff0c;找到一个3d 免费资源 3D Animations & Models | Unity Asset Store unity 里面window->package Manager 里面可以看到自己的asset &#xff0c;下载后…

Java SE入门及基础(43)

目录 File类 1. File类的作用 2. File类的使用 常用构造方法 示例 常用方法 1.获取文件相关信息 示例 2.文件相关的判断 示例 3.文件列表相关 示例 3. 递归 示例 1.使用递归求1~100的累加和。 2.使用递归打印文件夹下所有文件信息 练习 思考&#xff1a;如何删…

《Effective Modern C++》- 极精简版 36-42条

本文章属于专栏《业界Cpp进阶建议整理》 继续上篇《Effective Modern C》- 极精简版 30-35条。 本文列出《Effective Modern C》的36-42条的个人理解的极精简版本。 Item36、如果有异步的&#xff0c;请指定std::launch::async demo代码为&#xff1a; int calculateSum(int a…

MySQL 数据库压力测试

文章目录 前言1. 安装部署1.1 二进制安装1.2 源码安装 2. 服务器性能测试2.1 CPU2.2 内存2.3 磁盘 3. MySQL 基准测试3.1 参数解析3.2 压测命令3.3 输出解读3.4 结果分析 前言 Sysbench 是一个开源的多线程基准测试工具&#xff0c;也是目前使用最多的 MySQL 压力测试工具。本…

树莓派与电脑视频实时传输实现

编程环境 1、 树莓派 4B 2、 windows 编程语言 python 应用 tkinter scoket opencv 效果 视频同传 服务端视频初始化 服务端视频读取 windows 客户端接收视频流&#xff0c;队列存储 解析视频&#xff0c;存入队列 ui页面数据刷新 下载链接&#xff1a;https://…

什么是虚假唤醒?为什么会产生虚假唤醒?

什么是虚假唤醒&#xff1f; 当一定的条件触发时会唤醒很多在阻塞态的线程&#xff0c;但只有部分的线程唤醒是有用的&#xff0c;其余线程的唤醒是多余的。 比如说卖货&#xff0c;如果本来没有货物&#xff0c;突然进了一件货物&#xff0c;这时所有的顾客都被通知了&#x…

1178: 密码翻译(python)

题目描述 在情报传递过程中&#xff0c;为了防止情报被截获&#xff0c;往往需要对情报用一定的方式加密&#xff0c;简单的加密算法虽然不足以完全避免情报被破译&#xff0c;但仍然能防止情报被轻易的识别。我们给出一种最简的的加密方法&#xff0c;对给定的一个字符串&…