数据分析师如何快速发现数据质量问题
来源: | 作者:pmod6d781 | 发布时间: 2022-12-23 | 3950 次浏览 | 分享到:
在有成熟数据管理体系企业中做数据分析项目,数据分析师经过初期数据探索,就发现了很多数据质量问题。该企业有完善的数据模型设计,也有完备的数据管理流程。对于每日生产数据,有专职人员负责日常数据审核修正,不定期也邀请外部技术服务商进行数据治理。

企业用户好奇追问我们是如何发现这些数据质量问题的,当时习以为常,没有细想就回答“唯有谨慎认真而已”。但事后想想,除了数据分析师本身对数据更加敏感之外,还是有客观原因让数据分析师能在正统数据管理手段之外发现数据质量问题,同时也存在很多看起来“不值一提”的切入点,对其他数据分析项目都有参考意义。



示例案例



为让讨论更具象,参考实际项目引入一个虚拟案例(测试仪器模块的性能劣化分析)。一个车间有很多个不同类型的多功能测试台(TestBed),测试台配置不同仪器模块做测试,每轮测试持续若干天,分为安装(install)、清洁(clean)、正式测试三个阶段。在测试过程中,有各种状态监控(例如环境温度),每10分钟一条。数据库的E-R图下图所示。



一个具体仪器单元(表InstrumebtUnit)是专用的,属于某个固定的测试台(表TestBed),但与其他测试台的型号(unit_id)可能是相同的,并且一个型号的仪器在一个测试台最多配备1部。测试仪器的型号是分层次,这里假设2个层次(大类和细类)。测试周期数目(表TestTask的cycle字段)是按照测试仪器递增的,但相邻2个测试任务使用的测试仪器可能不同。



检查步骤



质量检测中,我们主要进行了3类检测,首先是直接基于当前数据库设计的schema进行检查(特别是schema的薄弱环节);然后根据主要业务约束,进行第二轮检查;最后,再通过少量案例端到端的探讨,获取业务领域的理解。这些步骤在实际中也是迭代执行。

1、基于data schema的检查

上图所示的data schema可以看出有2个潜在弱点:
1) task_id为代理主键,实际的组合主键是bed_id, unit_id与cycle,可能存在不唯一;
2) 仪器的unit_id是层次结构,存在引用层次不一致的可能性。

R语言、Python语言提供很多数据探索分析工具,如下表所示。


描述
R语言函数
组合主键的唯一性
组合主键的唯一性通常由应用逻辑来保证,但应用开发时并一并做这样的检查
aggregate(<anyField>~<compKey1>+<compKey2>+...+<compKeyN>,data=df,   FUN=length)
枚举量字段
所有的枚举类与业务领域模型是否一致
unique(<fieldName>)
多个枚举字段的组合关系
检查两个字段是否1:N关系(包括了层次结构),还是N:M关系

如果枚举值不多,可以用

table(<fieldName1>,<fieldName2>)

多个字段建的交叉关系

如果枚举值很多,可以用

aggregate(<fieldName1>~<fieldName2>,data=df, FUN=function(x){length(unique(x))})

字段数值分布
快速了解各个字段的数值分布,也可以发现一些业务语义上的超界
dfSummary(<dataFrame>)
对于数值变量,可以用range()函数
外键是否真发挥作用
因为代理主键的引入,很多外键失去本身的价值,通过两个表joint,看记录是否符合预期
merge(df1,df2,all.x=TRUE)


实际数据中也证实了我们的猜想。


TestTask中存在重复记录(按照bed_id, unit_idy与task唯一的语义),并且重复记录的内容不完全相同,应该是业务应用对于录入的测试任务没有做重复性检查。


TestTask中存在时间字段异常的情形,例如,竟然有task_start_time为2035年的记录。


表TestConditionMonitoring中与TestTask的起止时间(task_start_time和task_end_time规约到10分钟间隔),用bed_id, unit_id和时间字段做左joint之后,做填补(具体做法可以参阅《工业大数据分析算法实战》的2.2.2节),发现竟然有很多记录缺乏task值。包括3类原因,
1) TestConditionMonitoring在2017年前unit_id用的是大类,而TestTask一直用的是细类;
2) TestTask中存在测试周期缺失;

3) TestTask有些记录的起止时间不对。


上面问题的发现都是从data schema的薄弱点切入。包括:
1)代理主键;
2)层次性字段;
3)关键字段的值域。

2、结构约束条件的检查
对象建模中也有OCL (Object Constraint Language)等约束描述,但实际应用开发中应用较少。很多概念上的约束并没有在数据库或业务应用层面实现。

可以从领域模型或从业务逻辑的角度,把当前理解的约束逻辑明确列出来,通过分析代码的自动化手段,快速发现大量历史数据中的零星数据质量问题。


TestTask为例,它蕴含着时序结构。在选择同一个bed_id的记录后,按照task_start_time从小到大排列,第i个测试周期的起止时间记为task_start_time(i)、end_date(i),curtime为当前查询时间,task_end_time=NA表示当前任务还未结束。可以简要列出如下6条约束条件,第6条是个软约束:

1) task_start_time(i)< task_end_time(i)
2) task_start_time(i) is not NA & task_start_time(i)<= cur_time
3) task_end_time(i) is NA | task_end_time(i)<=cur_time
4) task_start_time(i+1)= task_end_time(i)
5) cycle(i)=cycle(j)+1, j=argmax(j: unit_id(j)=unit_id(i), j<i)

6) 6 Hours< task_end_time(i)- task_start_time(i)<5 Days.


根据这些规则,TestTask有几百条异常记录(1%左右)。根据每条记录的单独分析,除了
1) TestTask中存在测试周期缺失;2) TestTask有些记录的起止时间不对之外,还发现3) TestTask部分记录的unit_id是错的。

针对分析课题的关键字段,列出隐性的约束和假设
,无论对于数据质量问题识别,还是应用的边界条件检查都有很大帮助。

3、基于异常案例的探讨

很多数据异常可能是我们没有意识到的业务场景,但业务场景通常没有完善的记录,也很难靠访谈方式获得全面的了解。一个有效的获取方式就是拿具体案例,和业务专家深入探讨。

针对上面约束检查中发现的task_end_time(i)-   task_start_time(i)过短或过长的记录,做深入的个例分析。可以发现:1)部分是正常的例外业务场景造成的。例如,测试台出现故障长时间处于待修状态;测试中也时常采用一些新工艺;测试台之间存在交叉影响等;2)部分记录是周期划分不正确导致的,例如,在安装阶段出现了异常,短暂停留后成功进行二次安装,从业务逻辑上还是同一条TestTask记录,但被录成了2条记录。


《工业大数据分析实践》中,我们呼吁业务理解阶段需要进行业务上下文理解。理想情形下,如果之前的数据库系统或应用开发时有一个业务语义层面的领域模型(请参阅Eric Evans《领域驱动设计:软件核心复杂性应对之道》),这些问题就变得简单。


但这种跨领域协同实际执行起来有难度,造成绝大多数数据库和应用设计都不会积累下来领域模型。通常业务专家会做一定业务概念介绍,但通常不完备。跨领域交流时,业务专家不知道你不知道什么,数据分析师不知道自己不知道什么。图书、文档、业务专家介绍的大多是正常情形(甚至理想情形),而不是在日常使用中的各种实际情形。对于数据分析师而言,我们的优势是有实际数据,可以采用两边夹击的方式,基于当前的领域理解,整理出一个当前认知水平下的“领域模型”,再结合实际数据集中个别案例的理解,补充完善这个“领域模式”。

考虑跨领域交流的信息损失,全面展开的工作量太大,时间太长,且很难见效。这里推荐:针对数据分析中的关键字段,通过个例探讨获取对业务场景的深入认知。更深入的探讨,可以参阅Eric Evans一书中关于集装箱海运领域建模的案例。



主要原因总结



企业花了很大力气做数据治理,为什么数据分析师还是能够发现新的数据质量问题,原因有三。


视角不同:日常数据管理是以业务应用流程(单表)为中心,关注数值合法性和关联的合规性,关注少量记录;而数据分析是是以业务逻辑概念(多个表格关联合并后的宽表)为中心,关注“跨领域全量”记录,同时考虑领域对象结构(多个表关联结构、记录间结构和业务场景)关联、全量的角度做数据分析。很多单条看起来正常的记录,在上下文角度看可能是不正常的。


视野不同:日常数据管理视野宽,但没有明确目标;而数据分析项目通常有聚焦分析目标,视野很窄,但更深入。视野和深度二者不可兼得。

概念模型与数据模型的差异:很多业务语义上约束关系,并没有在实际数据库或数据应用中严格检查与遵循。例如,数据表通常用代理主键而不是自然主键,很多概念上约束关系可能没有生效。时间间隔(time   interval)关系约束(例如,不同生产周期的起止时间间隔不能重叠)通常需要业务应用来保证,但当一条新的记录写入时候,很多业务应用没有将其与历史记录做约束性检查。



总结



Data  Schema的设计是为了满足特定应用(例如MES)需求的,只要符合设计初衷,数据就不存在Data  Schema层面的质量问题;而数据分析的目的是解决一个物理世界中的问题,以物理语义看数据问题(不会完全迷信数据),并且通常要跨多个数据集,对数据集的要求与一个应用的需求可能不同,因而,数据分析项目中的“数据质量”问题除了Data  Schema层面,还要关心应用场景(Application Context)下的数据质量问题。Data  Schema层面的质量问题通常可以用数据模型(如关系数据表的3范式)、数据约束(如OCL,Object Constraint  Language)等形式化模型去描述,可以独立于具体的应用。而应用场景相关的数据质量问题,与研究问题的范畴和业务上下文有关,通常不容易发现,有一定规律但不存在通用的方法。各种数据系统、工具和企业级的数据治理大多集中在前者,而留给行业数据分析师的往往是后者,没有经验的数据分析师往往很难发现这些问题,造成了基于“问题数据训练出的机器学习模型不可信。


在数据分析项目中,关心的数据问题远远超过了Data   Schema层面的数据质量问题。有时候数据中包含的场景和信息远远超过了当前分析课题关心的范畴,这时候需要从现有数据中筛选出合适的数据;更多时候,数据分析问题的因素并没有完整的反映在数据中,数据反映的仅仅是部分生命周期的状态。这就要求数据分析师能够从业务上下文的角度去梳理问题的关键要素,以及它们之间的关系,审视数据在多大程度上刻画了问题的过程。业务上下文的理解也不是一个单向过程,数据中表现出的“异常”,很多时候是上下文理解的不完整。通过“业务的数据化”和“数据的业务化”迭代,不断加深对分析课题和数据集的理解。深入理解业务问题和数据集后,你会发现很多“你以为的不是你以为的”有趣问题。



参考文献


[1]田春华. 工业大数据分析算法实战[M].北京:机械工业出版社, 2022.

[2]田春华, 李闯, 刘家杨等. 工业大数据分析实战[M]. 北京:电子工业出版社, 2021.

[3]Eric Evans. 领域驱动设计:软件核心复杂性应对之道[M]. 陈大峰, 张泽鑫等译. 北京:人民邮电出版社, 2007.