2.数据变换
由于本案例的挖掘目标是对热水器用户的洗浴事件进行识别,这就需要从原始数据中识别出哪些状态记录是一个完整的用水事件(包括洗脸、洗手、刷牙、洗头、洗菜和洗浴等),从而再识别出用水事件中的洗浴事件;一次完整的用水事件是根据水流量和停顿时间间隔的阈值去划分的,所以本案例还建立了阈值寻优模型;为了提高在大量的一次完整用水事件中寻找洗浴事件的效率,本案例建立了筛选规则剔除可以明显判定不是洗浴的事件,得到建模数据样本集。数据变换流程如图10-2所示。
图10-2 数据变换流程图
(1)一次完整用水事件的划分模型
用户的用水数据存储在数据库中,记录了各种各样的用水事件,包括洗浴、洗手、刷牙、洗脸、洗衣和洗菜等,而且一次用水事件由数条甚至数千条的状态记录组成。所以,本案例首先需要在大量的状态记录中划分出哪些连续的数据是一次完整的用水事件。
在用水状态记录中,水流量不为0表明用户正在使用热水;而水流量为0时用户用热水发生停顿或者用热水结束。如果水流量为0的状态记录之间的时间间隔超过一个阈值T,则从该段水流量为0的状态记录向前找到最后一条水流量不为0的用水记录作为上一次用水事件的结束;向后找到水流量不为0的状态记录作为下一个用水事件的开始。划分模型的符号说明见表10-5。
表10-5 一次完整用水事件模型构建符号说明表
一次完整用水事件的划分步骤如下。
1)读取数据记录,识别到第一条水流量不为0的数据记录记为R1,按顺序识别接下来的一条水流量不为0数据记录为R2。
2)若gapi>T,则Ri+1与Ri及之间的数据记录不能划分到同一次用水事件。同时将Ri+1记录作为新的读取数据记录的开始,返回步骤1);若gapi<T,则将Ri+1与Ri之间数据记录的划分到同一次用水事件,并记录接下来的水流量不为0数据记录为Ri+2。
3)循环执行步骤2),直到数据记录读取完毕,结束事件划分。
使用Pandas对用户的用水数据进行一次完整用水事件的划分,阈值T暂时假设为4分钟,详细代码如代码清单10-1所示。
代码清单10-1 划分一次用水事件代码
#-*- coding: utf-8 -*- #用水事件划分 import pandas as pd threshold = pd.Timedelta(minutes = 4) #阈值为4分钟 inputfile = '../data/water_heater.xls' #输入数据路径,需要使用Excel格式 outputfile = '../tmp/dividsequence.xls' #输出数据路径,需要使用Excel格式 data = pd.read_excel(inputfile) data[u'发生时间'] = pd.to_datetime(data[u'发生时间'], format = '%Y%m%d%H%M%S') data = data[data[u'水流量'] > 0] #只要流量大于0的记录 d = data[u'发生时间'].diff() > threshold #相邻时间作差分,比较是否大于阈值 data[u'事件编号'] = d.cumsum() + 1 #通过累积求和的方式为事件编号 data.to_excel(outputfile)
代码详见:demo/code/divide_event.py
对用户的用水数据进行划分,划分结果如表10-6所示。
表10-6 用水数据划分结果
(2)用水事件阈值寻优模型
考虑到不同地区的人们用热水器的习惯不同,以及不同季节使用热水器时停顿的时长也可能不同,固定的停顿时长阈值对于某些特殊的情况的处理是不理想的,存在把一个事件划分为两个事件或者把两个事件合为一个事件的情况。所以,考虑到在不同的时间段内要更新阈值,本案例建立了阈值寻优模型来更新寻找最优的阈值,这样可以解决因时间变化和地域不同导致阈值存在差异的问题。
对某热水器用户的数据进行了不同阈值划分,得到了相应的事件个数,阈值变化与划分得到的事件个数如表10-7所示,阈值与划分事件个数关系如图10-3所示。
表10-7 某热水器用户家庭某时间段不同用水时间间隔阈值事件划分个数
图10-3 阈值与划分事件个数关系
图10-3中某段阈值范围内,下降趋势明显,说明在该段阈值范围内,用户的停顿习惯比较集中。如果趋势比较平缓,则说明用户的停顿习惯趋于稳定,所以取该段时间开始作为阈值,既不会将短的用水事件合并,又不会将长的用水事件拆开。在图10-3中,用户停顿热水的习惯在方框的位置趋于稳定,说明热水器用户的用水停顿习惯用方框开始的时间点作为划分阈值会有一个好的效果。
在图10-3中,曲线趋于稳定时,其方框开始的点的斜率趋于一个较小的值。为了用程序来识别这一特征,将这一特征提取为规则。可以从图10-4中相邻2个点之间斜率值的大小说明程序是如何识别图10-3方框中的起始时间的。
图10-4 斜率计算图
每个阈值对应一个点,计算每个阈值得到一个斜率指标。如图10-4所示,A点是要计算斜率指标的点,为了直观的展示,用下面的符号来进行说明,见表10-8。
表10-8 阈值寻优模型符号说明
根据(10-1)式,计算出kAB、kBC、kCD、kDE四个斜率。再计算出四个斜率之和的平均值K:
将K作为A点的斜率指标,特别指出横坐标上的最后4个点没有斜率指标,因为找不出在它以后的4个更长的阈值。但这不影响对最优阈值的寻找,因为可以提高阈值的上限,以使最后的4个阈值不是考虑范围内的阈值。
于是,阈值优化的结果如下:
当存在一个阈值的斜率指标K<1时,则取阈值最小的点A(可能存在多个阈值的斜率指标小于1)的横坐标xA作为用水事件划分的阈值,其中K<1中的1是经过实际数据验证的一个专家阈值。
当不存在K<1时,则找所有阈值中斜率指标最小的阈值;如果该阈值的斜率指标小于5,则取该阈值作为用水事件划分的阈值;如果该阈值的斜率指标不小于5,则阈值取默认值的阈值为4分钟。其中,斜率指标小于5中的5是经过实际数据验证的一个专家阈值。
使用Python对用户的用水数据划分阈值进行寻优,寻优区间在1分钟~9分钟,详细代码见代码清单10-2。
代码清单10-2 阈值寻优代码
#-*- coding: utf-8 -*- #阈值寻优 import numpy as np import pandas as pd inputfile = '../data/water_heater.xls' #输入数据路径,需要使用Excel格式 n = 4 #使用以后四个点的平均斜率 threshold = pd.Timedelta(minutes = 5) #专家阈值 data = pd.read_excel(inputfile) data[u'发生时间'] = pd.to_datetime(data[u'发生时间'], format = '%Y%m%d%H%M%S') data = data[data[u'水流量'] > 0] #只要流量大于0的记录 def event_num(ts): d = data[u'发生时间'].diff() > ts #相邻时间作差分,比较是否大于阈值 return d.sum() + 1 #这样直接返回事件数 dt = [pd.Timedelta(minutes = i) for i in np.arange(1, 9, 0.25)] h = pd.DataFrame(dt, columns = [u'阈值']) #定义阈值列 h[u'事件数'] = h[u'阈值'].apply(event_num) #计算每个阈值对应的事件数 h[u'斜率'] = h[u'事件数'].diff()/0.25 #计算每两个相邻点对应的斜率 h[u'斜率指标'] = pd.rolling_mean(h[u'斜率'].abs(), n) #采用后n个的斜率绝对值平均作为斜率 指标 ts = h[u'阈值'][h[u'斜率指标'].idxmin() - n] #注:用idxmin返回最小值的Index,由于rolling_mean()自动计算的是前n个斜率的绝对值平均 #所以结果要进行平移(-n) if ts > threshold: ts = pd.Timedelta(minutes = 4) print(ts)
代码详见:demo/code/threshold_optimization.py
根据读入的数据文件,进行阈值寻优,得到该段时间用水事件划分的最优阈值为4分钟。
(3)属性构造
本案例研究的是用水行为,可构造4类指标:时长指标、频率指标、用水的量化指标以及用水的波动指标。具体请参见表10-9。
表10-9 4类属性指标的构建表
对一次用水事件抽取主要的用水数据,具体见表10-10。
表10-10 一次用水事件的用水数据表
根据用水数据,得到用水事件的属性构造说明图,如图10-5所示。
图10-5 一次用水事件及相关属性说明
下面对4类指标的构建方法做详细说明。
时长类指标。由图10-5及表10-10可知,在20:00:10热水器记录到的数据还没有用水,而在20:00:12热水器记录有用水行为,所以,用水开始时间在20:00:10~20:00:12之间。考虑到网络不稳定导致网络数据传输延时数分钟或数小时等因素,取平均值会导致很大的偏差,综合分析构建“用水开始时间”为起始数据的时间减去“发送阈值”的一半,发送阈值是指热水器传输数据的频率的大小。同理构造用水结束时间、停顿开始时间和停顿结束时间等。图10-5中的“用水时长A”是“用水开始时间”到“停顿开始时间”的间隔时长,构建一次用水事件中“用水时长”为各段用水时长之和。同理构造总用水时长、停顿时长等。详细信息见表10-11。
频率类指标。统计一次用水事件中各种用水操作的频率。详细信息见表10-12。
用水量化指标。总用水量定义为:在水流量不为0时,一次用水事件(见表10-10)中每条状态记录的水流量与下一条状态记录的时间间隔的乘积。平均水流量定义为:总用水量与用水时长的商。详细信息见表10-13。
用水波动指标。“水流量波动”指标定义为:当前水流的值与平均水流量差的平方乘以持续时间的总和除以总的有水流量的时间。同理构造温度波动、热水量波动和停顿时长波动等指标。详细信息见表10-14。
表10-11 主要时长类指标构建说明
表10-12 频数类指标构建说明
表10-13 用水量化指标构建说明
表10-14 用水波动指标构建说明
(4)筛选得“候选洗浴事件”
洗浴事件的识别是建立在一次用水事件识别的基础上,也就是从已经划分好的一次用水事件中识别出哪些一次用水事件是洗浴事件。
首先,用3个比较宽松的条件筛选掉那些非常短暂的用水事件,将剩余的洗浴事件称为“候选洗浴事件”。这3个条件是“或”的关系。也就是说,只要一次完整的用水事件满足任意一个条件,就被判定为短暂用水事件,即会被筛选掉。3个筛选条件如下。
1)一次用水事件中总用水量(纯热水)小于y升。
2)用水时长小于100秒。
3)总用水时长小于120秒。
下面对y的合理取值进行探究。洗澡的水温一般为37~41℃。因为花洒喷头出水的温度变化也在37~41℃,所以热水器设定温度越高,热水器水的实际温度就越高,热水器热水的使用量就越少。
经过实验分析,热水器设定温度为50℃时,一次普通的洗浴时长为15分钟,总用水时长10分钟左右,热水的使用量为10~15升。
为了不影响特殊的短暂的洗浴事件,以及考虑到夏天用的热水较少,放宽范围假定热水器在设定温度为50℃时,一次洗浴的总热水使用量为5升,同时取洗浴温度的均值为39℃来计算热水器不同设定温度下的热水使用量阈值。
热水使用量模型变量符号说明,见表10-15。
表10-15 标准热水量换算模型符号说明
假定每次洗浴习惯变化不大且热水器水温恒定,则每次洗浴使用的热水的热量应该趋近于一个定值。如果热水器设定温度X调高使热水器水温变高,则一次洗浴使用的热水量就减少;相反,使用的热水量就增多。
假设两次洗浴事件热水和冷水混合后的花洒出水水温度恒为T摄氏度,总用水量不变且为M+V升,根据热量守恒建立方程组(10-2)。
其中(1)式是50℃的热水V升与M升C℃自来水混合得到M+V升T摄氏度的洗浴用水的热守恒公式。(2)式是X℃的热水Y升与M+V-Y升C℃自来水混合得到M+V升T℃的洗浴用水的热守恒公式。从而得出Y与X、C、V之间的关系。
其中,V是热水器的水恒为50℃时洗浴时的最低用水量。根据公式(10-4)可以计算用水事件在不同实际用水温度下的标准热水使用量。其中,自来水每月平均温度取平均室温。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论