铁路旅客流量预测——数据清洗

数据清洗是数据分析、数据挖掘中至关重要的步骤之一。它不仅会直接影响到数据分析、数据挖掘的结果,还有助于我们进一步认识数据。前车之鉴是写这篇文章的主要目的。希望本文能够帮助小伙伴们少踩些坑。
在正式介绍我清洗铁路旅客流量数据的过程之前,不免要首当其冲说明下题目及数据的来源。该数据集来自于第四届泰迪杯全国数据挖掘挑战赛B题。
##数据库设计
该数据集是以xls文件给出的,且xls文件内的内容格式复杂,不便于读取数据。所以,整理数据集,设计数据库是必要的。
设计数据库的原则是尽可能的涵盖梯形密度表提供所有的信息。我将数据分别存入5张表中:t_meteorology、t_passenger_flow、t_station_info、t_train_info和t_train_kezuolv。下面是创建这几张表的sql语句。

CREATE TABLE `meteorology_table` (
  `date` date NOT NULL COMMENT '日期',
  `weather` varchar(20) DEFAULT NULL COMMENT '天气状况 晴/晴',
  `temperature` varchar(20) DEFAULT '' COMMENT '气温 2℃/-5℃',
  `wind` varchar(20) DEFAULT NULL COMMENT '风力风向 南风4-5级/南风3-4级',
  `district` varchar(20) NOT NULL COMMENT '地区 ZD111',
  PRIMARY KEY (`date`,`district`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `passenger_flow_table` (
  `date` date NOT NULL COMMENT '日期',
  `trainId` varchar(20) NOT NULL COMMENT '车次',
  `station` varchar(20) NOT NULL COMMENT '车站',
  `stationNum` int(11) DEFAULT NULL COMMENT '该车次的第几个站',
  `inboundTime` time DEFAULT NULL COMMENT '进站时间',
  `outboundTime` time DEFAULT NULL,
  `upNum` int(11) DEFAULT NULL,
  `downNum` int(11) DEFAULT NULL,
  PRIMARY KEY (`trainId`,`date`,`station`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `station_info_table` (
  `station` varchar(20) NOT NULL COMMENT '车站',
  `district` varchar(20) DEFAULT NULL COMMENT '所属地区',
  `mileage` int(20) DEFAULT NULL COMMENT '里程(公里)\r\n假设所有的站都是在一条直线上\r\n里程指的是到ZD111-01的距离',
  PRIMARY KEY (`station`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `train_info_table` (
  `trainId` varchar(20) NOT NULL COMMENT '车次',
  `startStation` varchar(20) DEFAULT NULL COMMENT '始发站',
  `endStation` varchar(20) DEFAULT NULL COMMENT '终点站',
  `openDays` int(11) DEFAULT NULL COMMENT '开行天数',
  `riJunDingYuan` int(11) DEFAULT NULL COMMENT '日均定员',
  PRIMARY KEY (`trainId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `train_kezuolv_table` (
  `date` date NOT NULL COMMENT '日期',
  `trainId` varchar(20) NOT NULL COMMENT '车次',
  `keZuoLv` float DEFAULT NULL COMMENT '客座率',
  PRIMARY KEY (`date`,`trainId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

该数据库设计的缺点显而易见,没有包含梯形密度表的中间部分的数据,如图1红框中的内容。

![图1 没有存入数据库的数据](https://img-blog.csdn.net/2018043015403377?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMjI4NDYz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
图1 没有存入数据库的数据

##数据异常或缺失
###梯形密度表缺失

下载该数据集合后,初步浏览所下载的文件,发现所提供的数据的日期范围为2015年1月1日到2016年3月20日。由此,我下意识的想了下,是否会缺失某一天的数据呢?带着疑问,我按文件名浏览了一遍数据集。果不其然,被我一语中的。缺失的文件有20150324.xls、20150330.xls、20150331.xls、201507026.xls和20151031.xls。而20150826.xls虽然存在,但是没有任何内容,是个空文件。因此,20150826.xls也可以认为是缺失的。
针对这种情况,补全数据需要分为两步:
步骤1,补全每一天的运行车次;
步骤2,用均值或者其他方法补全上下车人数。(我用的是均值)
步骤1需要特别注意的是,要添加的车次是否在当天运行。数据集中所有车次运行频率如图2所示。从图2中可以看出,不是所有的车次在给定时间段内一直运行,而是有的运行几次,有的运行一段时间,还有的先运行几次,然后运行一段时间。

![所有车次运行频率](https://img-blog.csdn.net/20180430161524964?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMjI4NDYz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
图2 所有车次运行频率

因此,给缺失文件补全车次的原则如下:
(1)如果要添加的车次只出现几次,那么,该车次可以舍弃;
(2)如果要添加的车次某段时间连续出现,且缺失的文件日期正在这段时间内,那么添加该车次;
以上的梯形密度表缺失是因为文件缺失导致。下面的情况是由于某一天的文件缺了本应该存在的车次。
如图3,D52在20160202-20160302时间段内共出现23次,由此可以认为,该车次有6天是缺失的,需要在对应日期补全车次及上下车人数。

![D52出现频率](https://img-blog.csdn.net/20180430171507118?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMjI4NDYz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
图3 D52出现频率及时间
###梯形密度表内的数据缺失 >将梯形密度表内的数据数据库中导入数据时,并不是一帆风顺的,主要有这几种情况:日均定员缺失、客座率缺失、上车站或下车站缺失以及上下人数缺失。而这些意外情况都会引起你写的导数据的程序抛异常。下面详细地描述以上几种数据缺失。 ##### 上车站的个数和下车站的不对应 >正常情况下,列车的梯形密度表的上车站的个数比下车站的少一个。这是因为在列车的终点站没有上车人数,因此将表示终点站上车人数的这一列省略,如图4(a)。 但是,有些车次的梯形密度表的上、下车站的个数缺失,它俩的个数不符合上述规律。有的车次缺失某几个上车站、有的车次缺失某几个下车站,还有的车次上车站和下车站都缺失了。图4(b)是下车站缺失的情况,通过观察可以确定下车站缺失了ZD143。 ![正常的上下车站个数](https://img-blog.csdn.net/20180430204938605?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMjI4NDYz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
图4(a) 正常的上下车站个数
![异常的上下车站个数](https://img-blog.csdn.net/20180430205148541?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMjI4NDYz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
图4(b)异常的上下车站个数

同一车次,与正常的梯形密度表相比,如果上车站或下车站只缺少一个,那么只需当前的梯形密度表即可做出判断;如果上车站或下车站缺少多个,那么需要根据最近几天的相同车次的上下车站来判断,这是因为,有些车次对于某个站,有时候会停车,有时候则不会。此外,有些梯形密度表的上下车人数严重缺失,如G09车次在2015年08月03日,梯形密度表的上下车站个数为1、2(如图4©),而正常情况下应该为9、10(如图4(d)),这时,应该认为该梯形密度表整体缺失。
G09正常的梯形密度表

图4(c) G09正常的梯形密度表
![这里写图片描述](https://img-blog.csdn.net/20180430212600248?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMjI4NDYz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
图4(d) G09异常的梯形密度表
#####日均定员、客座率缺失 如图5所示,客座率缺失时只显示百分号“%” ![日均定员和客座率缺失](https://img-blog.csdn.net/20180430211252542?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMjI4NDYz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
图5 日均定员和客座率缺失
#####某站对应的上车人数、下车人数部分缺失 >上、下车人数合计处的“空白单元格”(姑且这么称呼),可能是0,也可能是空。如果是0的话,那么不做操作;如果是空的话,那么认为是对应的数据缺失。 ![空白单元格](https://img-blog.csdn.net/20180430211055201?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMjI4NDYz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
图6 空白单元格
#####上下车站名重复或者错误 如图7所示,2015年11月15日的G01的下车站名出现了重复。 ![重复的下车站](https://img-blog.csdn.net/20180430220030586?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMjI4NDYz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
重复的下车站

此外,数据集的少部分xls文件中上下车站名出现了汉字,而不是编码。该情况出现的位置分别为20150418.xls中的第852行(K08)和20150426.xls中的第1059行(k01))。这种情况通过与其它xls文件比较,便可以得到真实地名的编码。


以上就是我清洗数据时遇到的所有特殊情况。记录下来,希望对小伙伴们或多或少有些帮助。可能会有遗漏,希望大家指正。

猜你喜欢

转载自blog.csdn.net/qq_41228463/article/details/80148675