前段时间参加阿里天池中的智慧交通预测挑战赛,费了不少功夫初赛排名45进入了复赛,后续没有时间继续复赛了,但还是想总结一下,算法就不详述了,具体谈谈数据处理的一些问题与解决方案。适合想要学习的新手参考,欢迎大家提出意见
语言使用python+pycharm
数据与部分代码百度网盘地址:
http://pan.baidu.com/s/1jIGasnW
1. 读取数据
比赛中数据格式为txt,读取方式有两种,但为了方便进行后续的操作,采用python的库pandas进行读取,读入后的格式为dataFrame,同时具有行列索引,如下:
data=pd.read_table('F:/tianchi/new_gy_contest_traveltime_training_data_second.txt',sep=';')
也可以用pd.read_csv,效果一样
Sep用来说明txt的分隔符,需要观察源数据,有的是;or #or,等等,需要灵活使用,不然读出的数据是乱的
(1)有时候不想读入全部数据,可以这么办
data=pd.read_table('F:/tianchi/new_gy_contest_traveltime_training_data_second.txt',sep=';',nrows=100)
这样就只会读取前100行
(2)表头问题
如果你的数据有表头,那么读入的时候会自动将表头作为列名,如下:
如果没有表头,那么问题来了,它会自动将第一行数据作为表头,这不是我们想要的,那么就要这样:
A=pd.read_csv("mix_festival+weekend_result_0810.txt",sep='#',header=None)
那有的时候又需要使用自定义的表头怎么半呢,恩,手动添加
A.columns=['link_ID','date','time_interval','travel_time']
2. 合并不同数据
比赛中有三个数据表格,算是比较少的了,一般通过列名进行匹配合并
new_gy_contest_traveltime_training_data_second.txt
表头为link_ID;date;time_interval;travel_time
gy_contest_link_info.txt
表头为link_ID;length;width;link_class
gy_contest_link_top_update.txt
表头为link_ID;in_links;out_links;
可以发现具有公共列名link_ID,这也是合并的基础,合并方法如下:
data=pd.merge(数据1,数据2,on='link_ID')
3.列数据处理
(1)删除列数据
data.drop('time_interval',axis=1)说明一下,改变列名即可删除其他列,axis=1表示删除方向为列,默认为行
(2)添加列数据
比如源数据有一列为time_interval,我要把它分为start_time和end_time两列(这儿主要说明怎么新增列,不是怎么拆分)
可以这样:
start_time=[]
for i in data['time_interval']: i=str(i) start_time.append(int(i.split(',')[0])) data['start_time']=start_time #添加新的列start_time
要注意的是新增列的大小必须与原数据的大小相同,要不会发生意想不到的错误,可以试试
(3)排序
有时候你想排序,比如时间序列数据,怎么办,也简单
按照一个的大小来排
data=data.sort_values('linkID')
同时按照两个来排,注意先后顺序
data=data.sort_values(['linkID','start_time'])
4.数据分组,批量读入
(1)数据分组
比赛中一共有132条路的数据,想要查看每一条路(link_ID)的数据怎么办,python帮你解决
for name,group in data.groupby('link_ID'):
group.to_csv('F:/tianchi/new_data/{}.txt'.format(name),index=False)
ps:name为link_ID分组后每条路的名字,group为相应的数据,之后将没条路的数据存到本地txt文件,名字为每条路的link_ID,index=False表示不会将行索引存下来,你也可以根据其他的来分组
(2)数据批量操作
刚才根据每条路的ID名分为了132个txt文件,现在又想把它们合并为一个,也不难,只需要使用另外一个库glob
filename=glob.glob(r'F:/tianchi/data/*.txt')
filenames = filename
with open('F:/tianchi/data.txt', 'w') as outfile:
for fname in filenames:
with open(fname) as infile:
for line in infile:
outfile.write(line)
这样就会将数据保存在outfile这个文件里面,但这样做会有一个问题,如果132个文件都有表头,那么会将表头重复132次,这不是我们想要的,我们只需要一个表头或者不要,这也是可以解决的:
filename=glob.glob(r'F:/tianchi/5-x/*.txt') filenames = filename with open('F:/tianchi/data-top-test.txt', 'w')as outfile: for fname in filenames: with open(fname) as infile: for line in islice(infile, 1, None):#读取时跳过第一行 outfile.write(line)
这样就解决了,而且可以扩展
5.缺失数据处理
(1)查看是否有缺失值并统计数量
sub_demo[['link_ID','date','time_interval','t']].shape
#输出sub_demo上面相应列的大小
sub_demo[['link_ID','date','time_interval','t']].isnull().sum()
#输出sub_demo上面相应列的缺失值的数目
(2)填充缺失值
一种方法是使用pandas的fillna方法,如下
data.fillna(value=1)
data.fillna(method='ffill',limit=2,axis=1)
参数说明,value表示用什么填充,method表示填充方式,前向填充或者后向填充,即直接使用缺失值的前一个值或后一个值,limit表示可以连续填充的最大数量,axis表示填充的方向。
另一种方法是使用差值函数,如拉格朗日差值等
(3)时间缺失
比赛结果提交时需要自己构造132条路6月份8:00-9:00每隔两分钟的数据,那么需要先生成相应的格式,如下:
代码30多行,比较简单,放在网盘中了
6.将数据存为本地文件
data.to_csv('F:/tianchi/result/result.txt',index=False,header=None,sep='#') #生成提交文件
可以自己决定是否要索引,表头,何种分隔符等
时间有限也就暂时说到这里,还有缺失值匹配、时间格式等有机会再补充。