ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于LabVIEW的箱线图设计:从分位数算法到XY Graph绘图实践

基于LabVIEW的箱线图设计:从分位数算法到XY Graph绘图实践 在测试测量行业干了这么多年用LabVIEW处理的数据没有一千万也有八百万。箱线图这个需求看着简单真要在LabVIEW里做出来却让不少人挠头。它不像波形图那样加个控件就能用官方面板里根本没有现成的“箱线图”组件。我见过不少人最后把数据导到Origin或者Python里画做一次两次还行但要集成到自动化测试平台里数据不落地直接分析出图才是真需求。这篇文章我就把自己实际做“基于LabVIEW的箱线图设计”这套东西的完整思路写下来包括分位数算法选型、程序框图逻辑、绘图方案对比以及大数据量下怎么保证界面不卡。代码思路和关键参数都给你写清楚照着搭就能用。1. 为什要在LabVIEW里画箱线图以及它到底难在哪1.1 箱线图能解决什么问题先说个实际场景。我在做多通道温度采集的项目中每个通道每秒采50个点连续跑24小时一个通道就是432万个数据。如果用波形图直接看原始数据屏幕上就是一条密密麻麻的“毛虫”根本看不出通道间的一致性差异。这时候把数据压缩成箱线图每个通道显示五个关键统计量——最小值、下四分位数、中位数、上四分位数、最大值再标出离群点通道之间的分布差异一眼就能看出来。箱线图的核心价值是用五个数概括一批数据特别适合批量对比。比如十条产线的良率数据、八台设备同一测点的振动数据、二十批物料的硬度测试结果每批画一个箱子排成一排谁分布宽、谁中位数高、谁有异常点一目了然。这在QC报告、设备比对、长期监测场景里是刚需。1.2 LabVIEW没有原生控件的真相LabVIEW的控件面板里波形图、XY图、强度图都是现成的唯独没有Box Plot。原因也简单箱线图本质上是“统计图形”而不是“通用曲线”NI把统计功能放在了专门的模块里但那个模块并没有提供完整的图形化展示组件。所以我们要做的事就拆成了两块第一块是算第二块是画。算就是写程序计算五个统计量和离群点画就是用LabVIEW自带的XY图或者Picture控件把箱子画出来。搞清楚这个思路整个设计就有了主线。1.3 不要急着把数据导出去很多人的第一反应是算完分位数以后导出CSV再到Python里用matplotlib或者到网页上用ECharts画。我在网上也看到有人问“我计算了箱线图的几个分位线能够用ECharts做出箱线图吗”。能完全能ECharts画起来代码很少而且交互体验很好。但这套流程有两个硬伤。第一数据落地再导入对自动化测试平台来说多了一个中间环节程序没法一条链路跑完第二LabVIEW的实时性优势全丢了。如果你是做产线测试、设备监测这类需要程序自动出报告的场景直接在LabVIEW里画完嵌到前面板上才是正解。ECharts那条路适合做数据展示系统不适合做测量软件。2. 动手前先想清楚三种主流实现路线怎么选2.1 三条路线的优缺点对比我梳理过在LabVIEW里画箱线图的方案主流有三条方案实现思路优点缺点方案AXY Graph自绘用XY图多个plot分别画箱体、须线、离群点纯LabVIEW实现无外部依赖打包部署方便坐标轴标签需要自己处理多组数据排列稍麻烦方案BPicture控件自绘用Picture控件的绘图函数逐笔画线样式完全自定义最灵活坐标轴刻度要自己算代码量大开发周期长方案C调用Python/外部库LabVIEW调Python节点画图或生成HTML在浏览器里显示图形美观交互丰富依赖Python环境打包后目标机器要装解释器部署麻烦我的建议很直接绝大多数场景用方案A。XY Graph是LabVIEW的基础控件性能好、代码量适中、移植性好。方案B适合那种对图形样式有极致要求的比如要画带阴影的、要艺术字体的但开发成本成倍增加。方案C适合做上位机展示界面不适合做测量软件的一部分。2.2 我最终为什么选了XY Graph我这套设计最终用了XY Graph核心原因有三个。第一是部署省心。LabVIEW程序经常要打包成EXE发给现场工程师用方案C要额外装Python和相关库方案B代码量大且不好维护XY Graph方案打包以后什么都不用额外装。第二是性能稳定。XY Graph底层是原生绘图引擎画几千个点非常快。箱线图本身点数不多——每个箱子最多十几条线段加几个散点但底层数据可能是几十万条绘图层面基本没有压力。第三是代码结构清晰。箱体、须线、离群点各用独立的plot数据结构上天然分离后面想改颜色、改线宽、加图例都是改一个属性的事。2.3 大数据量场景下的处理原则做箱线图设计时我特别强调一个原则先压缩数据再交给显示控件。不管用XY Graph还是Picture都不要让原始的大数组直接参与绘图。举个例子我做的温湿度监测系统每个通道的原始数据要存库归档但显示给用户看的箱线图只用了从原始数据中算出来的8个值5个分位统计量加3个辅助量。这8个值是从几十万点里算出来的信息没有丢但绘制负担几乎为零。这个“数据压缩后再可视化”的思路是所有统计图设计的通用方法论不仅针对箱线图。3. 分位数算法才是真正的核心3.1 别在分位数定义上栽跟头箱线图画得对不对核心不是绘图代码而是分位数算得准不准。这里有个坑很多人都跳过分位数不是唯一的。同样是计算一组数据的第一四分位数Q1Excel的PERCENTILE.INC函数、Python numpy的percentile函数、Origin的统计功能算法的细节有差异。常见的有两种定义定义A线性插值法即numpy默认先算出位置h (n-1) * p其中n是数据个数p是分位点0.25、0.5、0.75然后对h上下两个数据做线性插值。定义B最近秩法位置算出来后四舍五入取整直接取那个秩次对应的数据值。如果数据量小两种定义差出的结果可能不一样数据量大了差异就小。做程序之前你得想清楚并用文档固定下来你到底用哪种定义以及为什么。我一般用线性插值法它和Python、Origin的结果一致性好便于跨工具核对。3.2 排序与线性插值的具体计算逻辑在LabVIEW里分位数计算的第一步是排序。用函数面板里的**“排序一维数组”**Sort 1D Array函数把输入数组升序排列。这个函数用得很多但有个细节要注意它只处理一维数组。如果你是多通道二维数组必须先抽取每一列形成单独的一维数组或者用重排数组维度函数把二维转成一维来处理。排序完以后计算分位数的公式我写成框图逻辑给你输入排序后数组X[0..n-1]分位点p 1. 计算位置 h (n-1) * p 2. 取整数部分 j floor(h) 3. 取小数部分 f h - j 4. 如果 j1 n 分位数 (1-f) * X[j] f * X[j1] 否则 分位数 X[n-1]LabVIEW实现的时候用“向下取整”函数得到j用“减”运算得到f然后按公式算就行。注意数组下标从0开始边界情况是p1时h正好等于n-1这时jn-1j1就越界了所以要加一个条件结构处理。3.3 从分位数到完整的箱线图数据包分位数计算函数最好封装成一个子VI输入是原始一维数组和一个分位点输出是分位数结果。这样主程序里要算Q1、Q2、Q3调用三次子VI就行。我习惯把这个子VI命名为“Quantile Calculate.vi”输入输出接线端定义清楚后面复用很方便。有了Q1、Q2、Q3接下来算箱线图需要的全部参数参数计算公式说明下四分位数Q1子VI计算p0.25箱体下边中位数Q2子VI计算p0.5箱体中间的线上四分位数Q3子VI计算p0.75箱体上边四分位距IQRQ3 - Q1衡量数据的中间50%离散程度下须线值max(最小值, Q1 - 1.5×IQR)触须的下端点上须线值min(最大值, Q3 1.5×IQR)触须的上端点离群点小于下须线或大于上须线的点单独标记出来这里1.5倍IQR是个经验系数统计学上比较通用的设定是1.5它对应的正态分布数据大约有0.7%的点会被判为离群点。如果你做的是某种特定行业的数据这个系数可以按行业规范调整但程序里最好做成前面板输入控件方便现场改不要写死。有个细节要提醒计算须线时下须线不是直接用Q1-1.5×IQR而是要和实际最小值取较大值上须线要和实际最大值取较小值。这样保证须线的端点落在真实数据的范围内不会出现须线超出数据范围的情况。4. 用XY Graph把箱线图真正画出来4.1 数据组织每个箱子需要几条plot线这是整个设计里最需要理清数据结构的地方。XY Graph支持多个plot我的方案中每个箱子由3条plot组成plot 1箱体画一个矩形框包括箱体四条边和须线。数据点按顺序连成一条闭合或不闭合的折线。plot 2中位数线单独的线画在箱子中间高度。plot 3离群点散点画在须线之外的异常数据位置。如果一次显示多组数据比如8个通道那就复制8份plot组。你可能会担心代码里硬编码8份会不会很臃肿实际落地时我建议用循环动态创建plot的方式配合属性节点设置每个plot的颜色和线型。4.2 箱体与须线的坐标点计算画箱子本质上是算出一串XY坐标点然后塞给XY Graph。假设这一组数据在横轴上占据的位置是x1.0箱体宽度设定为boxWidth0.4那么箱体矩形的四个角分别是(1.0 - boxWidth/2, Q1) - (1.0 boxWidth/2, Q1) - (1.0 boxWidth/2, Q3) - (1.0 - boxWidth/2, Q3) - (1.0 - boxWidth/2, Q1)这5个点连起来就是闭合箱体。须线是两根竖线从箱体底部中点向下须值画到底部Q1从箱体顶部中点向上须值画到顶部Q3。注意不是一根直通线中间要断开箱体区域因为箱体是填充的。所以plot 1的数据要按顺序组织成一条折线我一般把箱体点、下须线、上须线的点全部串成一个数组给plot 1。具体顺序是下须值 - Q1 - Q3 - 上须值然后反折回来组成一个“工”字形的折线。你可以把plot 1的线型设置成实线线宽调到1.5这样显示效果比较清晰。4.3 中位数线的特殊处理中位数线和箱体不一样它不需要考虑须线只是从箱体左边到右边画一条水平线段。两条线(1.0 - boxWidth/2, Q2) - (1.0 boxWidth/2, Q2)这条线我建议用不同的颜色比如橙色或者红色。在程序框图上只需要把两个点组成一个很小的二维数组用“创建XY”函数传给plot。注意中位数线不要和箱体边重合后淹没在箱体颜色里实际画出来要能明显区分。还有一个细节如果Q2正好等于Q1或者Q3比如数据集里有很多重复值箱体退化成一条线这是数据本身的问题显示上没问题。但如果你做的监测系统经常出现这种退化情况建议在程序里加一个判断箱体高度小于某个阈值时用文字提示“数据可能存在大量重复值”帮用户在数据分析阶段就发现问题。4.4 离群点怎么画才不凌乱离群点是比较有意思的部分。前面算出了所有离群点的数值但要注意离群点的横坐标不是固定的。同一个箱子的离群点都画在箱子的横轴位置附近但多个点挤在一起会重叠。我的处理方法是给每个离群点加一个微小的横向抖动或者按顺序在箱子宽度范围内水平均匀排开。实操中我一般按“抖动幅值0.05”来做也就是在x1.0±0.25的范围内把第i个离群点放在x1.0 - 0.2 0.4×i/(m-1)m为该箱子的离群点个数。这样点不会重叠一眼能看出大概有几个离群点。如果你不喜欢抖动也可以所有离群点都画在x1.0上点重叠时设置一定的透明度来表现密度。4.5 多组数据的X轴偏移与标签多组数据并排显示时每个箱子占用一个X轴位置。8个通道就分布在x1到x8上箱子宽度boxWidth建议设为0.6这样箱子之间有一点间隔布局不拥挤。X轴的刻度标签要根据通道号显示比如“通道1”“通道2”。在LabVIEW的XY Graph里刻度标签默认显示的是数值。需要右键属性 - 刻度和刻度线 - 格式把“格式”设置为字符串然后在最小值和最大值中配置每格显示的内容。这里有个技巧把X轴的最小值设为0.5最大值设为8.5每格为1刻度标签用数组“通道1、通道2...”来显示。坐标轴的范围和刻度其实可以在程序运行中用属性节点动态设置这样前面板一运行就自动调整好不需要手动配置。5. 实测经验性能优化与常见坑实录5.1 10万点数据的性能优化实测我在实验室里专门测过性能生成一个通道10万个随机数据从数据计算出分位数到绘图显示总耗时大约是230ms其中排序用了180ms绘图不到10ms。这个速度在实际项目中完全可以接受。如果你想让性能再进一步有两个方向。第一个是优化排序LabVIEW的排序一维数组用的是快速排序算法已经是比较优的。但如果你的数据量到了百万级别而且多次重复计算可以考虑只在需要更新时重新排序平时把排序结果缓存起来。第二个是降低调用频率我用事件结构做了一个“刷新统计”按钮用户点一下才重新计算和绘图而不是数据一变就立刻重绘。在连续采集模式下这样能避免界面反复闪烁。5.2 我在实际项目中踩过的几个坑坑一安装路径导致软件异常。LabVIEW安装或者打包出来的程序如果装到带中文或空格的路径下偶尔会出现一些奇怪的错误。比如LabVIEW卡在启动界面很多就是安装路径不干净导致的。建议统一用英文路径安装并且关掉杀毒软件实时防护再装装完再开启。坑二分位数计算没有考虑NaN值。如果你从DAQ采集卡直接拿数据偶尔会出现NaN或者Infinity。排序函数对NaN的处理结果和你想的不一样直接参与线性插值会让结果变成NaN整个箱子就画不出来了。所以子VI的输入前面要加一个“清洗数据”步骤把非数值的点剔除或者替换为边界值。坑三XY Graph创建多plot时颜色容易重复。LabVIEW默认的调色板颜色有限8个通道自动分配的颜色肉眼很容易混在一起。我在代码里用一个“颜色数组常量”来管理每个通道的颜色写死保证报表和屏幕上看到的一致。坑四打包发布时忘记包含VISA等驱动。你把程序打包成EXE发给别人如果用了VISA函数EXE运行的时候找不到VISA驱动会报错。打包时要在“安装程序属性”里勾选包含VISA运行时。同理如果调用了我前面说的子VI一定要确保子VI也被包含进项目库否则目标机器上字段为空。5.3 和Origin计算结果的一致性核对开发完这套箱线图设计后我特意用同一批数据在LabVIEW、Origin和Python三种工具里分别计算分位数做了交叉验证。3万个随机数三种工具算出的Q1、Q2、Q3在小数点后第4位有极小幅度的差异而箱线图的须线值和离群点完全一致。这说明两个问题第一只要选对分位数算法定义我用的线性插值法跨工具核对结果不会有问题第二箱线图的呈现效果对分位数的微小差异基本不敏感绘图层面不会出现肉眼可见的差别。在校准验收的时候可以用这个方法验证你的程序正确性——用一组已知答案的测试数据对比你程序的输出。用户在使用的时候我建议把“分位数算法说明”写到程序注释里包括用的哪种插值法、IQR系数是多少、离群点判定阈值。这样三个月后你自己回来看代码或者别人接手维护都能快速理解当时的计算逻辑不会出现“图是画出来了但不知道算的对不对”的局面。这套基于LabVIEW的箱线图设计我后来复用了好几个项目多通道温度监测、振动数据巡检、产线质量分析。核心代码基本没怎么改每次只是调整通道数量和颜色配置。希望你照着这个思路也能快速搭出一版跑通以后再根据自己行业的特殊需求做扩展。
返回列表