You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5771 lines
284 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 任务:预测道路某段时间的通行时间\n",
"\n",
"### 数据展示"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"from scipy.interpolate import UnivariateSpline\n",
"from sklearn import linear_model\n",
"import xgboost as xgb\n",
"from sklearn.utils import *"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"道路通行时间:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>time_interval</th>\n",
" <th>travel_time</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>4377906283422600514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 11:04:00,2017-05-06 11:06:00)</td>\n",
" <td>3.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906289434510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 10:42:00,2017-05-06 10:44:00)</td>\n",
" <td>1.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906285934510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 11:56:00,2017-05-06 11:58:00)</td>\n",
" <td>35.2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906285934510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 17:46:00,2017-05-06 17:48:00)</td>\n",
" <td>26.2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906287934510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 10:52:00,2017-05-06 10:54:00)</td>\n",
" <td>10.4</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID date time_interval \\\n",
"0 4377906283422600514 2017-05-06 [2017-05-06 11:04:00,2017-05-06 11:06:00) \n",
"1 3377906289434510514 2017-05-06 [2017-05-06 10:42:00,2017-05-06 10:44:00) \n",
"2 3377906285934510514 2017-05-06 [2017-05-06 11:56:00,2017-05-06 11:58:00) \n",
"3 3377906285934510514 2017-05-06 [2017-05-06 17:46:00,2017-05-06 17:48:00) \n",
"4 3377906287934510514 2017-05-06 [2017-05-06 10:52:00,2017-05-06 10:54:00) \n",
"\n",
" travel_time \n",
"0 3.0 \n",
"1 1.0 \n",
"2 35.2 \n",
"3 26.2 \n",
"4 10.4 "
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.read_csv('data/new_gy_contest_traveltime_training_data_second.txt',delimiter=';',dtype={'link_ID':object})\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"time_interval时间间隔两分钟为单位\n",
"\n",
"travel_time平均通行时间"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"道理长宽情况:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>length</th>\n",
" <th>width</th>\n",
" <th>link_class</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>4377906289869500514</td>\n",
" <td>57</td>\n",
" <td>3</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>4377906284594800514</td>\n",
" <td>247</td>\n",
" <td>9</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>4377906289425800514</td>\n",
" <td>194</td>\n",
" <td>3</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4377906284525800514</td>\n",
" <td>839</td>\n",
" <td>3</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>4377906284422600514</td>\n",
" <td>55</td>\n",
" <td>12</td>\n",
" <td>1</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID length width link_class\n",
"0 4377906289869500514 57 3 1\n",
"1 4377906284594800514 247 9 1\n",
"2 4377906289425800514 194 3 1\n",
"3 4377906284525800514 839 3 1\n",
"4 4377906284422600514 55 12 1"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"link_df = pd.read_csv('data/gy_contest_link_info.txt',delimiter=';',dtype={'link_ID':object})\n",
"link_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"length长度 width宽度 link_class类别"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"道路之间连接情况:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>in_links</th>\n",
" <th>out_links</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>4377906289869500514</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>4377906284594800514</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>4377906289425800514</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4377906284525800514</td>\n",
" <td>1</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>4377906284422600514</td>\n",
" <td>2</td>\n",
" <td>1</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID in_links out_links\n",
"0 4377906289869500514 1 1\n",
"1 4377906284594800514 1 1\n",
"2 4377906289425800514 1 1\n",
"3 4377906284525800514 1 1\n",
"4 4377906284422600514 2 1"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"link_tops = pd.read_csv('data/gy_contest_link_top_update.txt',delimiter=',',dtype={'link_ID':object})\n",
"link_tops.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 任务:预测未来一个月平均通行结果,每两分钟一次\n",
"回归任务\n",
"\n",
"构建时间序列,基于前几天或者前几十天的数据预测\n",
"https://tianchi.aliyun.com/competition/entrance/231598/information"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 数据集筛选与标签转换\n",
"数据集中有些数据可能由于异常情况导致不适合建模(堵车,维修等)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>time_interval</th>\n",
" <th>travel_time</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>4377906283422600514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 11:04:00,2017-05-06 11:06:00)</td>\n",
" <td>3.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906289434510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 10:42:00,2017-05-06 10:44:00)</td>\n",
" <td>1.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906285934510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 11:56:00,2017-05-06 11:58:00)</td>\n",
" <td>35.2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906285934510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 17:46:00,2017-05-06 17:48:00)</td>\n",
" <td>26.2</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906287934510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 10:52:00,2017-05-06 10:54:00)</td>\n",
" <td>10.4</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID date time_interval \\\n",
"0 4377906283422600514 2017-05-06 [2017-05-06 11:04:00,2017-05-06 11:06:00) \n",
"1 3377906289434510514 2017-05-06 [2017-05-06 10:42:00,2017-05-06 10:44:00) \n",
"2 3377906285934510514 2017-05-06 [2017-05-06 11:56:00,2017-05-06 11:58:00) \n",
"3 3377906285934510514 2017-05-06 [2017-05-06 17:46:00,2017-05-06 17:48:00) \n",
"4 3377906287934510514 2017-05-06 [2017-05-06 10:52:00,2017-05-06 10:54:00) \n",
"\n",
" travel_time \n",
"0 3.0 \n",
"1 1.0 \n",
"2 35.2 \n",
"3 26.2 \n",
"4 10.4 "
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>time_interval</th>\n",
" <th>travel_time</th>\n",
" <th>time_interval_begin</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>4377906283422600514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 11:04:00,2017-05-06 11:06:00)</td>\n",
" <td>3.0</td>\n",
" <td>2017-05-06 11:04:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906289434510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 10:42:00,2017-05-06 10:44:00)</td>\n",
" <td>1.0</td>\n",
" <td>2017-05-06 10:42:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906285934510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 11:56:00,2017-05-06 11:58:00)</td>\n",
" <td>35.2</td>\n",
" <td>2017-05-06 11:56:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906285934510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 17:46:00,2017-05-06 17:48:00)</td>\n",
" <td>26.2</td>\n",
" <td>2017-05-06 17:46:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906287934510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>[2017-05-06 10:52:00,2017-05-06 10:54:00)</td>\n",
" <td>10.4</td>\n",
" <td>2017-05-06 10:52:00</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID date time_interval \\\n",
"0 4377906283422600514 2017-05-06 [2017-05-06 11:04:00,2017-05-06 11:06:00) \n",
"1 3377906289434510514 2017-05-06 [2017-05-06 10:42:00,2017-05-06 10:44:00) \n",
"2 3377906285934510514 2017-05-06 [2017-05-06 11:56:00,2017-05-06 11:58:00) \n",
"3 3377906285934510514 2017-05-06 [2017-05-06 17:46:00,2017-05-06 17:48:00) \n",
"4 3377906287934510514 2017-05-06 [2017-05-06 10:52:00,2017-05-06 10:54:00) \n",
"\n",
" travel_time time_interval_begin \n",
"0 3.0 2017-05-06 11:04:00 \n",
"1 1.0 2017-05-06 10:42:00 \n",
"2 35.2 2017-05-06 11:56:00 \n",
"3 26.2 2017-05-06 17:46:00 \n",
"4 10.4 2017-05-06 10:52:00 "
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#截取开始时间\n",
"df['time_interval_begin'] = pd.to_datetime(df['time_interval'].map(lambda x: x[1:20]))\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"标签转换\n",
"<img src=\"assets/20201202211044.png\" width=\"100%\">\n",
"对于travel_time我们希望是右边的图越是正态分布越好预测"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"df = df.drop(['time_interval'],axis=1)\n",
"df['travel_time'] = np.log1p(df['travel_time'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"筛选方法"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"#剔除一些离群点如travel_time突然有几百分钟的时间可能是意外、道路维修或者统计错误\n",
"def quantile_clip(group):\n",
" # 选择一定的百分比过滤\n",
" group[group < group.quantile(.05)] = group.quantile(.05)\n",
" group[group > group.quantile(.95)] = group.quantile(.95)\n",
" return group"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>time_interval_begin</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>4377906283422600514</td>\n",
" <td>2017-05-06</td>\n",
" <td>1.386294</td>\n",
" <td>2017-05-06 11:04:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906289434510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>0.693147</td>\n",
" <td>2017-05-06 10:42:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906285934510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>3.589059</td>\n",
" <td>2017-05-06 11:56:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906285934510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>3.303217</td>\n",
" <td>2017-05-06 17:46:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906287934510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>2.251292</td>\n",
" <td>2017-05-06 10:52:00</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID date travel_time time_interval_begin\n",
"0 4377906283422600514 2017-05-06 1.386294 2017-05-06 11:04:00\n",
"1 3377906289434510514 2017-05-06 0.693147 2017-05-06 10:42:00\n",
"2 3377906285934510514 2017-05-06 3.589059 2017-05-06 11:56:00\n",
"3 3377906285934510514 2017-05-06 3.303217 2017-05-06 17:46:00\n",
"4 3377906287934510514 2017-05-06 2.251292 2017-05-06 10:52:00"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#对每条道路(link_ID),每天执行(date)\n",
"df['travel_time'] = df.groupby(['link_ID','date'])['travel_time'].transform(quantile_clip)\n",
"df.head(5)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"#根据需求选择样本数据比如预测高峰时刻如早上6-8、中午下午13-18\n",
"df = df.loc[(df['time_interval_begin'].dt.hour.isin([6,7,8,13,14,15,16,17,18]))]"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"#保存处理结果\n",
"df.to_csv('data/raw_data.txt',header=True,index=None,sep=';',mode='w')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 缺失值预处理"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>time_interval_begin</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906285934510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>3.303217</td>\n",
" <td>2017-05-06 17:46:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906287934510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>1.887070</td>\n",
" <td>2017-05-06 14:36:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906287674510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>1.931521</td>\n",
" <td>2017-05-06 06:30:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906287886510514</td>\n",
" <td>2017-05-06</td>\n",
" <td>3.616309</td>\n",
" <td>2017-05-06 07:32:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>4377906283759500514</td>\n",
" <td>2017-05-06</td>\n",
" <td>2.140066</td>\n",
" <td>2017-05-06 13:24:00</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID date travel_time time_interval_begin\n",
"0 3377906285934510514 2017-05-06 3.303217 2017-05-06 17:46:00\n",
"1 3377906287934510514 2017-05-06 1.887070 2017-05-06 14:36:00\n",
"2 3377906287674510514 2017-05-06 1.931521 2017-05-06 06:30:00\n",
"3 3377906287886510514 2017-05-06 3.616309 2017-05-06 07:32:00\n",
"4 4377906283759500514 2017-05-06 2.140066 2017-05-06 13:24:00"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.read_csv('data/raw_data.txt',delimiter=';',parse_dates=['time_interval_begin'],dtype={'link_ID':object})\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"如上第一行中2017-05-06 17:46:00那么是不是没有17:48、17:50所以我们需要补充"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>length</th>\n",
" <th>width</th>\n",
" <th>link_class</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>4377906289869500514</td>\n",
" <td>57</td>\n",
" <td>3</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>4377906284594800514</td>\n",
" <td>247</td>\n",
" <td>9</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>4377906289425800514</td>\n",
" <td>194</td>\n",
" <td>3</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4377906284525800514</td>\n",
" <td>839</td>\n",
" <td>3</td>\n",
" <td>1</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>4377906284422600514</td>\n",
" <td>55</td>\n",
" <td>12</td>\n",
" <td>1</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID length width link_class\n",
"0 4377906289869500514 57 3 1\n",
"1 4377906284594800514 247 9 1\n",
"2 4377906289425800514 194 3 1\n",
"3 4377906284525800514 839 3 1\n",
"4 4377906284422600514 55 12 1"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"link_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"DatetimeIndex(['2017-03-01 00:00:00', '2017-03-01 00:02:00',\n",
" '2017-03-01 00:04:00', '2017-03-01 00:06:00',\n",
" '2017-03-01 00:08:00'],\n",
" dtype='datetime64[ns]', freq='2T')"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"date_range = pd.date_range('2017-03-01 00:00:00','2017-07-31 23:58:00',freq='2min')\n",
"date_range[:5]"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 00:00:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 00:02:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 00:04:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 00:06:00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 00:08:00</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin\n",
"0 4377906289869500514 2017-03-01 00:00:00\n",
"1 4377906289869500514 2017-03-01 00:02:00\n",
"2 4377906289869500514 2017-03-01 00:04:00\n",
"3 4377906289869500514 2017-03-01 00:06:00\n",
"4 4377906289869500514 2017-03-01 00:08:00"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#给每个ID做出每一个时刻\n",
"new_index = pd.MultiIndex.from_product([link_df['link_ID'].unique(),date_range],\n",
" names=['link_ID', 'time_interval_begin'])\n",
"new_df = pd.DataFrame(index=new_index).reset_index()\n",
"new_df.head() # 此时每个ID都有从2017-03-01 00:00:00到2017-03-71 23:58:00的时间间隔"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 00:00:00</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 00:02:00</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 00:04:00</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 00:06:00</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 00:08:00</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date travel_time\n",
"0 4377906289869500514 2017-03-01 00:00:00 NaN NaN\n",
"1 4377906289869500514 2017-03-01 00:02:00 NaN NaN\n",
"2 4377906289869500514 2017-03-01 00:04:00 NaN NaN\n",
"3 4377906289869500514 2017-03-01 00:06:00 NaN NaN\n",
"4 4377906289869500514 2017-03-01 00:08:00 NaN NaN"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#原来的表里也有部分值,进行合并,出现大量缺失值\n",
"df2 = pd.merge(new_df, df,on=['link_ID','time_interval_begin'],how='left')\n",
"df2.head()"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"#筛选时间段数据\n",
"df2 = df2.loc[(df2['time_interval_begin'].dt.hour.isin([6,7,8,13,14,15,16,17,18]))]\n",
"df2 = df2.loc[~((df2['time_interval_begin'].dt.year == 2017) & \n",
" (df2['time_interval_begin'].dt.month == 7) & \n",
" (df2['time_interval_begin'].dt.hour.isin([8,15,18])))]\n",
"df2 = df2.loc[~((df2['time_interval_begin'].dt.year == 2017) & \n",
" (df2['time_interval_begin'].dt.month == 3) & \n",
" (df2['time_interval_begin'].dt.day == 31))]\n",
"\n",
"df2['date'] = df2['time_interval_begin'].dt.strftime('%Y-%m-%d')"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>180</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" </tr>\n",
" <tr>\n",
" <th>181</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" </tr>\n",
" <tr>\n",
" <th>182</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" </tr>\n",
" <tr>\n",
" <th>183</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" </tr>\n",
" <tr>\n",
" <th>184</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date travel_time\n",
"180 4377906289869500514 2017-03-01 06:00:00 2017-03-01 2.174752\n",
"181 4377906289869500514 2017-03-01 06:02:00 2017-03-01 2.174752\n",
"182 4377906289869500514 2017-03-01 06:04:00 2017-03-01 2.174752\n",
"183 4377906289869500514 2017-03-01 06:06:00 2017-03-01 2.174752\n",
"184 4377906289869500514 2017-03-01 06:08:00 2017-03-01 2.174752"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df2.head()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
"#保存中间结果\n",
"df2.to_csv('data/pre_trainning.txt',header=True,index=None,sep=';',mode='w')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 补全时间序列"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>travel_time2</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>180</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" <td>2.174752</td>\n",
" </tr>\n",
" <tr>\n",
" <th>181</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" <td>2.174752</td>\n",
" </tr>\n",
" <tr>\n",
" <th>182</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" <td>2.174752</td>\n",
" </tr>\n",
" <tr>\n",
" <th>183</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" <td>2.174752</td>\n",
" </tr>\n",
" <tr>\n",
" <th>184</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" <td>2.174752</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date travel_time \\\n",
"180 4377906289869500514 2017-03-01 06:00:00 2017-03-01 2.174752 \n",
"181 4377906289869500514 2017-03-01 06:02:00 2017-03-01 2.174752 \n",
"182 4377906289869500514 2017-03-01 06:04:00 2017-03-01 2.174752 \n",
"183 4377906289869500514 2017-03-01 06:06:00 2017-03-01 2.174752 \n",
"184 4377906289869500514 2017-03-01 06:08:00 2017-03-01 2.174752 \n",
"\n",
" travel_time2 \n",
"180 2.174752 \n",
"181 2.174752 \n",
"182 2.174752 \n",
"183 2.174752 \n",
"184 2.174752 "
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = df2\n",
"df['travel_time2'] = df['travel_time']\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"多个月统计-季节性变化"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"def date_trend(group):\n",
" tmp = group.groupby('date_hour').mean().reset_index()\n",
" \n",
" def nan_helper(y):\n",
" return np.isnan(y), lambda z: z.nonzero()[0]\n",
" \n",
" y = tmp['travel_time'].values\n",
" nans, x = nan_helper(y)\n",
" if group.link_ID.values[0] in ['3377906282328510514','3377906283328510514',\n",
" '4377906280784800514','9377906281555510514']:\n",
" tmp['date_trend'] = group['travel_time'].median()\n",
" else:\n",
" regr = linear_model.LinearRegression()\n",
" regr.fit(x(~nans).reshape(-1,1), y[~nans].reshape(-1,1))\n",
" tmp['date_trend'] = regr.predict(tmp.index.values.reshape(-1,1)).ravel()\n",
" group = pd.merge(group,tmp[['date_trend','date_hour']], on='date_hour',how='left')\n",
" return group"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>travel_time2</th>\n",
" <th>date_hour</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>180</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" <td>2.174752</td>\n",
" <td>2017-03-01-06</td>\n",
" </tr>\n",
" <tr>\n",
" <th>181</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" <td>2.174752</td>\n",
" <td>2017-03-01-06</td>\n",
" </tr>\n",
" <tr>\n",
" <th>182</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" <td>2.174752</td>\n",
" <td>2017-03-01-06</td>\n",
" </tr>\n",
" <tr>\n",
" <th>183</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" <td>2.174752</td>\n",
" <td>2017-03-01-06</td>\n",
" </tr>\n",
" <tr>\n",
" <th>184</th>\n",
" <td>4377906289869500514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>2.174752</td>\n",
" <td>2.174752</td>\n",
" <td>2017-03-01-06</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date travel_time \\\n",
"180 4377906289869500514 2017-03-01 06:00:00 2017-03-01 2.174752 \n",
"181 4377906289869500514 2017-03-01 06:02:00 2017-03-01 2.174752 \n",
"182 4377906289869500514 2017-03-01 06:04:00 2017-03-01 2.174752 \n",
"183 4377906289869500514 2017-03-01 06:06:00 2017-03-01 2.174752 \n",
"184 4377906289869500514 2017-03-01 06:08:00 2017-03-01 2.174752 \n",
"\n",
" travel_time2 date_hour \n",
"180 2.174752 2017-03-01-06 \n",
"181 2.174752 2017-03-01-06 \n",
"182 2.174752 2017-03-01-06 \n",
"183 2.174752 2017-03-01-06 \n",
"184 2.174752 2017-03-01-06 "
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 基于小时进行预测,如果基于整体预测,结果可能不准确定,我们先算小时对结果的影响\n",
"df['date_hour'] = df.time_interval_begin.map(lambda x: x.strftime('%Y-%m-%d-%H'))\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"道路每小时通行时间的回归结果\n",
"<img src=\"assets/20201202221436.png\" width=\"100%\">\n",
"左图:回归预测,蓝色线是回归线,红色是时间\n",
"右图:对某几个道路,直接用中位数预测"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>travel_time2</th>\n",
" <th>date_hour</th>\n",
" <th>date_trend</th>\n",
" </tr>\n",
" <tr>\n",
" <th>link_ID</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th rowspan=\"5\" valign=\"top\">3377906280028510514</th>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>2017-03-01-06</td>\n",
" <td>1.960745</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>2017-03-01-06</td>\n",
" <td>1.960745</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>2017-03-01-06</td>\n",
" <td>1.960745</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>2017-03-01-06</td>\n",
" <td>1.960745</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>2017-03-01-06</td>\n",
" <td>1.960745</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date \\\n",
"link_ID \n",
"3377906280028510514 0 3377906280028510514 2017-03-01 06:00:00 2017-03-01 \n",
" 1 3377906280028510514 2017-03-01 06:02:00 2017-03-01 \n",
" 2 3377906280028510514 2017-03-01 06:04:00 2017-03-01 \n",
" 3 3377906280028510514 2017-03-01 06:06:00 2017-03-01 \n",
" 4 3377906280028510514 2017-03-01 06:08:00 2017-03-01 \n",
"\n",
" travel_time travel_time2 date_hour date_trend \n",
"link_ID \n",
"3377906280028510514 0 NaN NaN 2017-03-01-06 1.960745 \n",
" 1 NaN NaN 2017-03-01-06 1.960745 \n",
" 2 NaN NaN 2017-03-01-06 1.960745 \n",
" 3 NaN NaN 2017-03-01-06 1.960745 \n",
" 4 NaN NaN 2017-03-01-06 1.960745 "
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = df.groupby('link_ID').apply(date_trend)\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"蓝线回归得到的值存在 df['date trend']里,此时 travel_time 就更新为 df['travel_time']= df['travel_time']-df['date_trend'],表示date_trend作为大的趋势已经被线性回归决定了,剩下的就是研究这个残差了,之后训练和预测都是基于残差,最后用预测出来的残差加上相应的date_trend即可得到需要的预测值"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>travel_time2</th>\n",
" <th>date_trend</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date travel_time \\\n",
"0 3377906280028510514 2017-03-01 06:00:00 2017-03-01 NaN \n",
"1 3377906280028510514 2017-03-01 06:02:00 2017-03-01 NaN \n",
"2 3377906280028510514 2017-03-01 06:04:00 2017-03-01 NaN \n",
"3 3377906280028510514 2017-03-01 06:06:00 2017-03-01 NaN \n",
"4 3377906280028510514 2017-03-01 06:08:00 2017-03-01 NaN \n",
"\n",
" travel_time2 date_trend \n",
"0 NaN 1.960745 \n",
"1 NaN 1.960745 \n",
"2 NaN 1.960745 \n",
"3 NaN 1.960745 \n",
"4 NaN 1.960745 "
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = df.drop(['date_hour','link_ID'],axis=1)\n",
"df = df.reset_index()\n",
"df = df.drop('level_1',axis=1)\n",
"df['travel_time'] = df['travel_time'] - df['date_trend']\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"日变化量(分钟)"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
"def minute_trend(group):\n",
" tmp = group.groupby('hour_minute').mean().reset_index()\n",
" #s的值越小对数据的拟合越好但是存在过拟合风险\n",
" spl = UnivariateSpline(tmp.index, tmp['travel_time'].values, s=0.5)\n",
" tmp['minute_trend'] = spl(tmp.index)\n",
" group = pd.merge(group, tmp[['minute_trend', 'hour_minute']], on='hour_minute', how='left')\n",
" return group"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>travel_time2</th>\n",
" <th>date_trend</th>\n",
" <th>hour_minute</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>06-00</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>06-02</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>06-04</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>06-06</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>06-08</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date travel_time \\\n",
"0 3377906280028510514 2017-03-01 06:00:00 2017-03-01 NaN \n",
"1 3377906280028510514 2017-03-01 06:02:00 2017-03-01 NaN \n",
"2 3377906280028510514 2017-03-01 06:04:00 2017-03-01 NaN \n",
"3 3377906280028510514 2017-03-01 06:06:00 2017-03-01 NaN \n",
"4 3377906280028510514 2017-03-01 06:08:00 2017-03-01 NaN \n",
"\n",
" travel_time2 date_trend hour_minute \n",
"0 NaN 1.960745 06-00 \n",
"1 NaN 1.960745 06-02 \n",
"2 NaN 1.960745 06-04 \n",
"3 NaN 1.960745 06-06 \n",
"4 NaN 1.960745 06-08 "
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df['hour_minute'] = df.time_interval_begin.map(lambda x: x.strftime('%H-%M'))\n",
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>travel_time2</th>\n",
" <th>date_trend</th>\n",
" <th>hour_minute</th>\n",
" <th>minute_trend</th>\n",
" </tr>\n",
" <tr>\n",
" <th>link_ID</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th rowspan=\"5\" valign=\"top\">3377906280028510514</th>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>06-00</td>\n",
" <td>-0.252121</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>06-02</td>\n",
" <td>-0.246743</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>06-04</td>\n",
" <td>-0.241428</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>06-06</td>\n",
" <td>-0.236176</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>06-08</td>\n",
" <td>-0.230986</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date \\\n",
"link_ID \n",
"3377906280028510514 0 3377906280028510514 2017-03-01 06:00:00 2017-03-01 \n",
" 1 3377906280028510514 2017-03-01 06:02:00 2017-03-01 \n",
" 2 3377906280028510514 2017-03-01 06:04:00 2017-03-01 \n",
" 3 3377906280028510514 2017-03-01 06:06:00 2017-03-01 \n",
" 4 3377906280028510514 2017-03-01 06:08:00 2017-03-01 \n",
"\n",
" travel_time travel_time2 date_trend hour_minute \\\n",
"link_ID \n",
"3377906280028510514 0 NaN NaN 1.960745 06-00 \n",
" 1 NaN NaN 1.960745 06-02 \n",
" 2 NaN NaN 1.960745 06-04 \n",
" 3 NaN NaN 1.960745 06-06 \n",
" 4 NaN NaN 1.960745 06-08 \n",
"\n",
" minute_trend \n",
"link_ID \n",
"3377906280028510514 0 -0.252121 \n",
" 1 -0.246743 \n",
" 2 -0.241428 \n",
" 3 -0.236176 \n",
" 4 -0.230986 "
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df=df.groupby('link_ID').apply(minute_trend)\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"与季节残差一样,回归得到的值存在 df['minute_trend']里,因此现在的travel_time再次更新为 df['travel_time]= df['travel_time']-df['minute_trend]"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [],
"source": [
"df = df.drop(['hour_minute', 'link_ID'], axis=1)\n",
"df = df.reset_index()\n",
"df = df.drop('level_1',axis=1)\n",
"df['travel_time'] = df['travel_time'] - df['minute_trend']"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>travel_time2</th>\n",
" <th>date_trend</th>\n",
" <th>minute_trend</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.252121</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.246743</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.241428</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.236176</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.230986</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date travel_time \\\n",
"0 3377906280028510514 2017-03-01 06:00:00 2017-03-01 NaN \n",
"1 3377906280028510514 2017-03-01 06:02:00 2017-03-01 NaN \n",
"2 3377906280028510514 2017-03-01 06:04:00 2017-03-01 NaN \n",
"3 3377906280028510514 2017-03-01 06:06:00 2017-03-01 NaN \n",
"4 3377906280028510514 2017-03-01 06:08:00 2017-03-01 NaN \n",
"\n",
" travel_time2 date_trend minute_trend \n",
"0 NaN 1.960745 -0.252121 \n",
"1 NaN 1.960745 -0.246743 \n",
"2 NaN 1.960745 -0.241428 \n",
"3 NaN 1.960745 -0.236176 \n",
"4 NaN 1.960745 -0.230986 "
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [],
"source": [
"link_infos = pd.read_csv('data/gy_contest_link_info.txt',delimiter=';',dtype={'link_ID':object})\n",
"link_tops = pd.read_csv('data/gy_contest_link_top_update.txt',delimiter=',',dtype={'link_ID':object})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"基本上大概的走势已经被 date_trend和 hour_trend决定了,剩下就是建模得到这个travel_time如何围绕这两个trends上下变化的\n",
"\n",
"选择训练特征:"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>travel_time2</th>\n",
" <th>date_trend</th>\n",
" <th>minute_trend</th>\n",
" <th>length</th>\n",
" <th>width</th>\n",
" <th>links_num</th>\n",
" <th>area</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.252121</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.246743</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.241428</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.236176</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.230986</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date travel_time \\\n",
"0 3377906280028510514 2017-03-01 06:00:00 2017-03-01 NaN \n",
"1 3377906280028510514 2017-03-01 06:02:00 2017-03-01 NaN \n",
"2 3377906280028510514 2017-03-01 06:04:00 2017-03-01 NaN \n",
"3 3377906280028510514 2017-03-01 06:06:00 2017-03-01 NaN \n",
"4 3377906280028510514 2017-03-01 06:08:00 2017-03-01 NaN \n",
"\n",
" travel_time2 date_trend minute_trend length width links_num area \n",
"0 NaN 1.960745 -0.252121 48 3 2 144 \n",
"1 NaN 1.960745 -0.246743 48 3 2 144 \n",
"2 NaN 1.960745 -0.241428 48 3 2 144 \n",
"3 NaN 1.960745 -0.236176 48 3 2 144 \n",
"4 NaN 1.960745 -0.230986 48 3 2 144 "
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"link_infos = pd.merge(link_infos, link_tops, on=['link_ID'], how='left')\n",
"link_infos['links_num'] = link_infos['in_links']+link_infos['out_links']\n",
"link_infos['area'] = link_infos['length'] * link_infos['width']\n",
"df = pd.merge(df, link_infos[['link_ID','length','width', 'links_num', 'area']], on=['link_ID'], how='left')\n",
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>travel_time2</th>\n",
" <th>date_trend</th>\n",
" <th>minute_trend</th>\n",
" <th>length</th>\n",
" <th>width</th>\n",
" <th>links_num</th>\n",
" <th>area</th>\n",
" <th>vacation</th>\n",
" <th>minute</th>\n",
" <th>hour</th>\n",
" <th>day</th>\n",
" <th>week_day</th>\n",
" <th>month</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.252121</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>0</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.246743</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>2</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.241428</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>4</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.236176</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>6</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.230986</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>8</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date travel_time \\\n",
"0 3377906280028510514 2017-03-01 06:00:00 2017-03-01 NaN \n",
"1 3377906280028510514 2017-03-01 06:02:00 2017-03-01 NaN \n",
"2 3377906280028510514 2017-03-01 06:04:00 2017-03-01 NaN \n",
"3 3377906280028510514 2017-03-01 06:06:00 2017-03-01 NaN \n",
"4 3377906280028510514 2017-03-01 06:08:00 2017-03-01 NaN \n",
"\n",
" travel_time2 date_trend minute_trend length width links_num area \\\n",
"0 NaN 1.960745 -0.252121 48 3 2 144 \n",
"1 NaN 1.960745 -0.246743 48 3 2 144 \n",
"2 NaN 1.960745 -0.241428 48 3 2 144 \n",
"3 NaN 1.960745 -0.236176 48 3 2 144 \n",
"4 NaN 1.960745 -0.230986 48 3 2 144 \n",
"\n",
" vacation minute hour day week_day month \n",
"0 0.0 0 6 1 3 3 \n",
"1 0.0 2 6 1 3 3 \n",
"2 0.0 4 6 1 3 3 \n",
"3 0.0 6 6 1 3 3 \n",
"4 0.0 8 6 1 3 3 "
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#时间相关特征\n",
"df.loc[df['date'].isin(['2017-04-02','2017-04-03','2017-04-04','2017-04-29','2017-04-30',\n",
" '2017-05-01','2017-05-28','2017-05-29','2017-05-30']),'vacation']=1\n",
"\n",
"df.loc[~df['date'].isin(['2017-04-02','2017-04-03','2017-04-04','2017-04-29','2017-04-30',\n",
" '2017-05-01','2017-05-28','2017-05-29','2017-05-30']),'vacation']=0\n",
"\n",
"df['minute'] = df['time_interval_begin'].dt.minute\n",
"df['hour'] = df['time_interval_begin'].dt.hour\n",
"df['day'] = df['time_interval_begin'].dt.day\n",
"df['week_day'] = df['time_interval_begin'].map(lambda x: x.weekday() + 1)\n",
"df['month'] = df['time_interval_begin'].dt.month\n",
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [],
"source": [
"def mean_time(group):\n",
" group['link_ID_en'] = group['travel_time'].mean()\n",
" return group"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>travel_time2</th>\n",
" <th>date_trend</th>\n",
" <th>minute_trend</th>\n",
" <th>length</th>\n",
" <th>width</th>\n",
" <th>links_num</th>\n",
" <th>area</th>\n",
" <th>vacation</th>\n",
" <th>minute</th>\n",
" <th>hour</th>\n",
" <th>day</th>\n",
" <th>week_day</th>\n",
" <th>month</th>\n",
" <th>link_ID_en</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.252121</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>0</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>0.000138</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.246743</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>2</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>0.000138</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.241428</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>4</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>0.000138</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.236176</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>6</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>0.000138</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.230986</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>8</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>0.000138</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date travel_time \\\n",
"0 3377906280028510514 2017-03-01 06:00:00 2017-03-01 NaN \n",
"1 3377906280028510514 2017-03-01 06:02:00 2017-03-01 NaN \n",
"2 3377906280028510514 2017-03-01 06:04:00 2017-03-01 NaN \n",
"3 3377906280028510514 2017-03-01 06:06:00 2017-03-01 NaN \n",
"4 3377906280028510514 2017-03-01 06:08:00 2017-03-01 NaN \n",
"\n",
" travel_time2 date_trend minute_trend length width links_num area \\\n",
"0 NaN 1.960745 -0.252121 48 3 2 144 \n",
"1 NaN 1.960745 -0.246743 48 3 2 144 \n",
"2 NaN 1.960745 -0.241428 48 3 2 144 \n",
"3 NaN 1.960745 -0.236176 48 3 2 144 \n",
"4 NaN 1.960745 -0.230986 48 3 2 144 \n",
"\n",
" vacation minute hour day week_day month link_ID_en \n",
"0 0.0 0 6 1 3 3 0.000138 \n",
"1 0.0 2 6 1 3 3 0.000138 \n",
"2 0.0 4 6 1 3 3 0.000138 \n",
"3 0.0 6 6 1 3 3 0.000138 \n",
"4 0.0 8 6 1 3 3 0.000138 "
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = df.groupby('link_ID').apply(mean_time)\n",
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>travel_time2</th>\n",
" <th>date_trend</th>\n",
" <th>minute_trend</th>\n",
" <th>length</th>\n",
" <th>width</th>\n",
" <th>links_num</th>\n",
" <th>area</th>\n",
" <th>vacation</th>\n",
" <th>minute</th>\n",
" <th>hour</th>\n",
" <th>day</th>\n",
" <th>week_day</th>\n",
" <th>month</th>\n",
" <th>link_ID_en</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.252121</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>0</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>75</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.246743</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>2</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>75</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.241428</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>4</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>75</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.236176</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>6</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>75</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.230986</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>8</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>75</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date travel_time \\\n",
"0 3377906280028510514 2017-03-01 06:00:00 2017-03-01 NaN \n",
"1 3377906280028510514 2017-03-01 06:02:00 2017-03-01 NaN \n",
"2 3377906280028510514 2017-03-01 06:04:00 2017-03-01 NaN \n",
"3 3377906280028510514 2017-03-01 06:06:00 2017-03-01 NaN \n",
"4 3377906280028510514 2017-03-01 06:08:00 2017-03-01 NaN \n",
"\n",
" travel_time2 date_trend minute_trend length width links_num area \\\n",
"0 NaN 1.960745 -0.252121 48 3 2 144 \n",
"1 NaN 1.960745 -0.246743 48 3 2 144 \n",
"2 NaN 1.960745 -0.241428 48 3 2 144 \n",
"3 NaN 1.960745 -0.236176 48 3 2 144 \n",
"4 NaN 1.960745 -0.230986 48 3 2 144 \n",
"\n",
" vacation minute hour day week_day month link_ID_en \n",
"0 0.0 0 6 1 3 3 75 \n",
"1 0.0 2 6 1 3 3 75 \n",
"2 0.0 4 6 1 3 3 75 \n",
"3 0.0 6 6 1 3 3 75 \n",
"4 0.0 8 6 1 3 3 75 "
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 通行时间长的编号大\n",
"sorted_link = np.sort(df['link_ID_en'].unique())\n",
"df['link_ID_en'] = df['link_ID_en'].map(lambda x: np.argmin(x >= sorted_link))\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"标准化"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {},
"outputs": [],
"source": [
"def std(group):\n",
" group['travel_time_std'] = np.std(group['travel_time'])\n",
" return group"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>travel_time2</th>\n",
" <th>date_trend</th>\n",
" <th>minute_trend</th>\n",
" <th>length</th>\n",
" <th>width</th>\n",
" <th>links_num</th>\n",
" <th>area</th>\n",
" <th>vacation</th>\n",
" <th>minute</th>\n",
" <th>hour</th>\n",
" <th>day</th>\n",
" <th>week_day</th>\n",
" <th>month</th>\n",
" <th>link_ID_en</th>\n",
" <th>travel_time_std</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.252121</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>0</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>75</td>\n",
" <td>0.223232</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.246743</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>2</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>75</td>\n",
" <td>0.223232</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.241428</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>4</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>75</td>\n",
" <td>0.223232</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.236176</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>6</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>75</td>\n",
" <td>0.223232</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.230986</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>8</td>\n",
" <td>6</td>\n",
" <td>1</td>\n",
" <td>3</td>\n",
" <td>3</td>\n",
" <td>75</td>\n",
" <td>0.223232</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date travel_time \\\n",
"0 3377906280028510514 2017-03-01 06:00:00 2017-03-01 NaN \n",
"1 3377906280028510514 2017-03-01 06:02:00 2017-03-01 NaN \n",
"2 3377906280028510514 2017-03-01 06:04:00 2017-03-01 NaN \n",
"3 3377906280028510514 2017-03-01 06:06:00 2017-03-01 NaN \n",
"4 3377906280028510514 2017-03-01 06:08:00 2017-03-01 NaN \n",
"\n",
" travel_time2 date_trend minute_trend length width links_num area \\\n",
"0 NaN 1.960745 -0.252121 48 3 2 144 \n",
"1 NaN 1.960745 -0.246743 48 3 2 144 \n",
"2 NaN 1.960745 -0.241428 48 3 2 144 \n",
"3 NaN 1.960745 -0.236176 48 3 2 144 \n",
"4 NaN 1.960745 -0.230986 48 3 2 144 \n",
"\n",
" vacation minute hour day week_day month link_ID_en travel_time_std \n",
"0 0.0 0 6 1 3 3 75 0.223232 \n",
"1 0.0 2 6 1 3 3 75 0.223232 \n",
"2 0.0 4 6 1 3 3 75 0.223232 \n",
"3 0.0 6 6 1 3 3 75 0.223232 \n",
"4 0.0 8 6 1 3 3 75 0.223232 "
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = df.groupby('link_ID').apply(std)\n",
"df['travel_time'] = df['travel_time'] / df['travel_time_std']\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"缺失时间预测"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [],
"source": [
"params = {\n",
" 'learning_rate':0.2,\n",
" 'n_estimators':30,\n",
" 'subsample':0.8,\n",
" 'colsample_bytree':0.6,\n",
" 'max_depth':10,\n",
" 'min_child_weight':1,\n",
" 'reg_alpha':0,\n",
" 'gamma':0\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>travel_time2</th>\n",
" <th>date_trend</th>\n",
" <th>minute_trend</th>\n",
" <th>length</th>\n",
" <th>area</th>\n",
" <th>vacation</th>\n",
" <th>...</th>\n",
" <th>day_27</th>\n",
" <th>day_28</th>\n",
" <th>day_29</th>\n",
" <th>day_30</th>\n",
" <th>day_31</th>\n",
" <th>month_3</th>\n",
" <th>month_4</th>\n",
" <th>month_5</th>\n",
" <th>month_6</th>\n",
" <th>month_7</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.252121</td>\n",
" <td>48</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.246743</td>\n",
" <td>48</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.241428</td>\n",
" <td>48</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.236176</td>\n",
" <td>48</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.230986</td>\n",
" <td>48</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5 rows × 103 columns</p>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date travel_time \\\n",
"0 3377906280028510514 2017-03-01 06:00:00 2017-03-01 NaN \n",
"1 3377906280028510514 2017-03-01 06:02:00 2017-03-01 NaN \n",
"2 3377906280028510514 2017-03-01 06:04:00 2017-03-01 NaN \n",
"3 3377906280028510514 2017-03-01 06:06:00 2017-03-01 NaN \n",
"4 3377906280028510514 2017-03-01 06:08:00 2017-03-01 NaN \n",
"\n",
" travel_time2 date_trend minute_trend length area vacation ... \\\n",
"0 NaN 1.960745 -0.252121 48 144 0.0 ... \n",
"1 NaN 1.960745 -0.246743 48 144 0.0 ... \n",
"2 NaN 1.960745 -0.241428 48 144 0.0 ... \n",
"3 NaN 1.960745 -0.236176 48 144 0.0 ... \n",
"4 NaN 1.960745 -0.230986 48 144 0.0 ... \n",
"\n",
" day_27 day_28 day_29 day_30 day_31 month_3 month_4 month_5 month_6 \\\n",
"0 0 0 0 0 0 1 0 0 0 \n",
"1 0 0 0 0 0 1 0 0 0 \n",
"2 0 0 0 0 0 1 0 0 0 \n",
"3 0 0 0 0 0 1 0 0 0 \n",
"4 0 0 0 0 0 1 0 0 0 \n",
"\n",
" month_7 \n",
"0 0 \n",
"1 0 \n",
"2 0 \n",
"3 0 \n",
"4 0 \n",
"\n",
"[5 rows x 103 columns]"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.get_dummies(df, columns=['links_num','width','minute','hour',\n",
" 'week_day','day','month'])\n",
"df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"训练的数据train_df为travel_time非空的数据而数据集test_df为travel_time空的数据"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['length', 'area', 'vacation', 'link_ID_en', 'links_num_2', 'links_num_3', 'links_num_4', 'links_num_5', 'width_3', 'width_6', 'width_9', 'width_12', 'width_15', 'minute_0', 'minute_2', 'minute_4', 'minute_6', 'minute_8', 'minute_10', 'minute_12', 'minute_14', 'minute_16', 'minute_18', 'minute_20', 'minute_22', 'minute_24', 'minute_26', 'minute_28', 'minute_30', 'minute_32', 'minute_34', 'minute_36', 'minute_38', 'minute_40', 'minute_42', 'minute_44', 'minute_46', 'minute_48', 'minute_50', 'minute_52', 'minute_54', 'minute_56', 'minute_58', 'hour_6', 'hour_7', 'hour_8', 'hour_13', 'hour_14', 'hour_15', 'hour_16', 'hour_17', 'hour_18', 'week_day_1', 'week_day_2', 'week_day_3', 'week_day_4', 'week_day_5', 'week_day_6', 'week_day_7', 'day_1', 'day_2', 'day_3', 'day_4', 'day_5', 'day_6', 'day_7', 'day_8', 'day_9', 'day_10', 'day_11', 'day_12', 'day_13', 'day_14', 'day_15', 'day_16', 'day_17', 'day_18', 'day_19', 'day_20', 'day_21', 'day_22', 'day_23', 'day_24', 'day_25', 'day_26', 'day_27', 'day_28', 'day_29', 'day_30', 'day_31', 'month_3', 'month_4', 'month_5', 'month_6', 'month_7']\n"
]
}
],
"source": [
"feature = df.columns.values.tolist()\n",
"train_feature = [x for x in feature if \n",
" x not in ['link_ID', 'time_interval_begin', 'travel_time', 'date',\n",
" 'travel_time2', 'minute_trend', 'travel_time_std', 'date_trend']]\n",
"\n",
"train_df = df.loc[~df['travel_time'].isnull()] # 获取非空的值,~是非空意思\n",
"test_df = df.loc[df['travel_time2'].isnull()].copy()\n",
"\n",
"print(train_feature)"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(3165426, 103)\n",
"(1883574, 103)\n"
]
}
],
"source": [
"print(train_df.shape)\n",
"print(test_df.shape)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"训练数据切分"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [],
"source": [
"from sklearn.model_selection import train_test_split\n",
"X = train_df[train_feature].values\n",
"y = train_df['travel_time'].values\n",
"\n",
"X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=0)\n",
"\n",
"eval_set = [(X_test, y_test)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"训练回归模型来预测缺失值"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[09:21:48] WARNING: C:/Jenkins/workspace/xgboost-win64_release_0.90/src/objective/regression_obj.cu:152: reg:linear is now deprecated in favor of reg:squarederror.\n",
"[0]\tvalidation_0-rmse:1.07239\n",
"Will train until validation_0-rmse hasn't improved in 10 rounds.\n",
"[1]\tvalidation_0-rmse:1.04051\n",
"[2]\tvalidation_0-rmse:1.0181\n",
"[3]\tvalidation_0-rmse:1.00329\n",
"[4]\tvalidation_0-rmse:0.994137\n",
"[5]\tvalidation_0-rmse:0.986071\n",
"[6]\tvalidation_0-rmse:0.980012\n",
"[7]\tvalidation_0-rmse:0.975637\n",
"[8]\tvalidation_0-rmse:0.972596\n",
"[9]\tvalidation_0-rmse:0.970479\n",
"[10]\tvalidation_0-rmse:0.968498\n",
"[11]\tvalidation_0-rmse:0.967078\n",
"[12]\tvalidation_0-rmse:0.966369\n",
"[13]\tvalidation_0-rmse:0.965318\n",
"[14]\tvalidation_0-rmse:0.964468\n",
"[15]\tvalidation_0-rmse:0.96396\n",
"[16]\tvalidation_0-rmse:0.962917\n",
"[17]\tvalidation_0-rmse:0.962312\n",
"[18]\tvalidation_0-rmse:0.961388\n",
"[19]\tvalidation_0-rmse:0.960701\n",
"[20]\tvalidation_0-rmse:0.960348\n",
"[21]\tvalidation_0-rmse:0.959666\n",
"[22]\tvalidation_0-rmse:0.959202\n",
"[23]\tvalidation_0-rmse:0.958588\n",
"[24]\tvalidation_0-rmse:0.958098\n",
"[25]\tvalidation_0-rmse:0.956764\n",
"[26]\tvalidation_0-rmse:0.956351\n",
"[27]\tvalidation_0-rmse:0.955532\n",
"[28]\tvalidation_0-rmse:0.955296\n",
"[29]\tvalidation_0-rmse:0.954658\n",
" length area vacation link_ID_en links_num_2 links_num_3 links_num_4 \\\n",
"0 48 144 0.0 75 1 0 0 \n",
"1 48 144 0.0 75 1 0 0 \n",
"2 48 144 0.0 75 1 0 0 \n",
"3 48 144 0.0 75 1 0 0 \n",
"4 48 144 0.0 75 1 0 0 \n",
"\n",
" links_num_5 width_3 width_6 ... day_27 day_28 day_29 day_30 day_31 \\\n",
"0 0 1 0 ... 0 0 0 0 0 \n",
"1 0 1 0 ... 0 0 0 0 0 \n",
"2 0 1 0 ... 0 0 0 0 0 \n",
"3 0 1 0 ... 0 0 0 0 0 \n",
"4 0 1 0 ... 0 0 0 0 0 \n",
"\n",
" month_3 month_4 month_5 month_6 month_7 \n",
"0 1 0 0 0 0 \n",
"1 1 0 0 0 0 \n",
"2 1 0 0 0 0 \n",
"3 1 0 0 0 0 \n",
"4 1 0 0 0 0 \n",
"\n",
"[5 rows x 95 columns]\n",
"<class 'pandas.core.frame.DataFrame'>\n",
"Int64Index: 1883574 entries, 0 to 5048999\n",
"Data columns (total 95 columns):\n",
"length int64\n",
"area int64\n",
"vacation float64\n",
"link_ID_en int64\n",
"links_num_2 uint8\n",
"links_num_3 uint8\n",
"links_num_4 uint8\n",
"links_num_5 uint8\n",
"width_3 uint8\n",
"width_6 uint8\n",
"width_9 uint8\n",
"width_12 uint8\n",
"width_15 uint8\n",
"minute_0 uint8\n",
"minute_2 uint8\n",
"minute_4 uint8\n",
"minute_6 uint8\n",
"minute_8 uint8\n",
"minute_10 uint8\n",
"minute_12 uint8\n",
"minute_14 uint8\n",
"minute_16 uint8\n",
"minute_18 uint8\n",
"minute_20 uint8\n",
"minute_22 uint8\n",
"minute_24 uint8\n",
"minute_26 uint8\n",
"minute_28 uint8\n",
"minute_30 uint8\n",
"minute_32 uint8\n",
"minute_34 uint8\n",
"minute_36 uint8\n",
"minute_38 uint8\n",
"minute_40 uint8\n",
"minute_42 uint8\n",
"minute_44 uint8\n",
"minute_46 uint8\n",
"minute_48 uint8\n",
"minute_50 uint8\n",
"minute_52 uint8\n",
"minute_54 uint8\n",
"minute_56 uint8\n",
"minute_58 uint8\n",
"hour_6 uint8\n",
"hour_7 uint8\n",
"hour_8 uint8\n",
"hour_13 uint8\n",
"hour_14 uint8\n",
"hour_15 uint8\n",
"hour_16 uint8\n",
"hour_17 uint8\n",
"hour_18 uint8\n",
"week_day_1 uint8\n",
"week_day_2 uint8\n",
"week_day_3 uint8\n",
"week_day_4 uint8\n",
"week_day_5 uint8\n",
"week_day_6 uint8\n",
"week_day_7 uint8\n",
"day_1 uint8\n",
"day_2 uint8\n",
"day_3 uint8\n",
"day_4 uint8\n",
"day_5 uint8\n",
"day_6 uint8\n",
"day_7 uint8\n",
"day_8 uint8\n",
"day_9 uint8\n",
"day_10 uint8\n",
"day_11 uint8\n",
"day_12 uint8\n",
"day_13 uint8\n",
"day_14 uint8\n",
"day_15 uint8\n",
"day_16 uint8\n",
"day_17 uint8\n",
"day_18 uint8\n",
"day_19 uint8\n",
"day_20 uint8\n",
"day_21 uint8\n",
"day_22 uint8\n",
"day_23 uint8\n",
"day_24 uint8\n",
"day_25 uint8\n",
"day_26 uint8\n",
"day_27 uint8\n",
"day_28 uint8\n",
"day_29 uint8\n",
"day_30 uint8\n",
"day_31 uint8\n",
"month_3 uint8\n",
"month_4 uint8\n",
"month_5 uint8\n",
"month_6 uint8\n",
"month_7 uint8\n",
"dtypes: float64(1), int64(3), uint8(91)\n",
"memory usage: 235.3 MB\n",
"None\n"
]
}
],
"source": [
"regressor = xgb.XGBRegressor(learning_rate=params['learning_rate'],\n",
" n_estimators=params['n_estimators'],\n",
" booster='gbtree', objective='reg:linear',\n",
" n_jobs=-1,subsample=params['subsample'],\n",
" colsample_bytree=params['colsample_bytree'],\n",
" random_state=0,max_depth=params['max_depth'],\n",
" gamma=params['gamma'],\n",
" min_child_weight=params['min_child_weight'],\n",
" reg_alpha=params['reg_alpha'])\n",
"regressor.fit(X_train,y_train,verbose=True,early_stopping_rounds=10,eval_set=eval_set)\n",
"print(test_df[train_feature].head())\n",
"print(test_df[train_feature].info())\n",
"test_df['prediction'] = regressor.predict(test_df[train_feature].values)"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [],
"source": [
"df = pd.merge(df, test_df[['link_ID','time_interval_begin','prediction']],\n",
" on=['link_ID','time_interval_begin'],how='left')"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd # 数据处理包\n",
"import numpy as np # 数据处理包\n",
"import matplotlib.pyplot as plt # 图形处理包\n",
"\n",
"\n",
"def importance_plt(feats_list, feats_importance, png_savename=0):\n",
" \"\"\"\n",
" 功能:打印特征重要图\n",
" why: 能看出哪个特征更重要继而对特征做相关衍生也可以讲特征使用次数为0的特征去掉防止冗余。\n",
" feats_list: 特征名list类型可以用如下方法获取X.columns.values # 获取全部特征\n",
" feats_importance: 已训练过的模型的特征重要性\n",
" xgb和lgb可以用如下方法获得:\n",
" feats_importance = clf.feature_importances_ # 获取特征使用次数\n",
" 长这样array([0.00567917, 0.00615975,],dtype=float32)\n",
" png_savename: 保存图片的名字,默认不保存\n",
" return: 打印出特征重要性图\n",
" \"\"\"\n",
" sorted_idx = np.argsort(feats_importance)\n",
" \n",
" plt.figure(figsize=(10, 55))\n",
" # 下面是画图操作\n",
" plt.barh(range(len(sorted_idx)), feats_importance[sorted_idx], align='center')\n",
"# plt.yticks(range(len(sorted_idx)), feats_list[sorted_idx], align='center')\n",
" plt.yticks(range(len(sorted_idx)), np.array(feats_list)[sorted_idx])\n",
" plt.xlabel(\"Importance\")\n",
" plt.title(\"Feature importances\")\n",
" if png_savename:\n",
" plt.savefig(\"特征重要性.png\", dpi=500, bbox_inches='tight') # 由于特征过多图片过大,所以需要这些处理才能让图片全部保存下来\n",
" plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 720x3960 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"importance_plt(train_feature, regressor.feature_importances_)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"最重要的是vacation是否是假期对结果的影响非常重要"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"还原预测结果"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {},
"outputs": [],
"source": [
"df['imputation1'] = df['travel_time'].isnull()\n",
"df['travel_time'] = df['travel_time'].fillna(value=df['prediction'])\n",
"df['travel_time'] = (df['travel_time']\n",
" * np.array(df['travel_time_std'])\n",
" + np.array(df['minute_trend'])\n",
" + np.array(df['date_trend']))"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>time_interval_begin</th>\n",
" <th>date</th>\n",
" <th>travel_time</th>\n",
" <th>travel_time2</th>\n",
" <th>date_trend</th>\n",
" <th>minute_trend</th>\n",
" <th>length</th>\n",
" <th>area</th>\n",
" <th>vacation</th>\n",
" <th>...</th>\n",
" <th>day_29</th>\n",
" <th>day_30</th>\n",
" <th>day_31</th>\n",
" <th>month_3</th>\n",
" <th>month_4</th>\n",
" <th>month_5</th>\n",
" <th>month_6</th>\n",
" <th>month_7</th>\n",
" <th>prediction</th>\n",
" <th>imputation1</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.252121</td>\n",
" <td>48</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>-0.220903</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>1.664941</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.246743</td>\n",
" <td>48</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>-0.219772</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>1.671675</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.241428</td>\n",
" <td>48</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>-0.213418</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>1.676886</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.236176</td>\n",
" <td>48</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>-0.213602</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>2017-03-01</td>\n",
" <td>1.682314</td>\n",
" <td>NaN</td>\n",
" <td>1.960745</td>\n",
" <td>-0.230986</td>\n",
" <td>48</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>...</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>-0.212535</td>\n",
" <td>True</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5 rows × 105 columns</p>\n",
"</div>"
],
"text/plain": [
" link_ID time_interval_begin date travel_time \\\n",
"0 3377906280028510514 2017-03-01 06:00:00 2017-03-01 1.659311 \n",
"1 3377906280028510514 2017-03-01 06:02:00 2017-03-01 1.664941 \n",
"2 3377906280028510514 2017-03-01 06:04:00 2017-03-01 1.671675 \n",
"3 3377906280028510514 2017-03-01 06:06:00 2017-03-01 1.676886 \n",
"4 3377906280028510514 2017-03-01 06:08:00 2017-03-01 1.682314 \n",
"\n",
" travel_time2 date_trend minute_trend length area vacation ... \\\n",
"0 NaN 1.960745 -0.252121 48 144 0.0 ... \n",
"1 NaN 1.960745 -0.246743 48 144 0.0 ... \n",
"2 NaN 1.960745 -0.241428 48 144 0.0 ... \n",
"3 NaN 1.960745 -0.236176 48 144 0.0 ... \n",
"4 NaN 1.960745 -0.230986 48 144 0.0 ... \n",
"\n",
" day_29 day_30 day_31 month_3 month_4 month_5 month_6 month_7 \\\n",
"0 0 0 0 1 0 0 0 0 \n",
"1 0 0 0 1 0 0 0 0 \n",
"2 0 0 0 1 0 0 0 0 \n",
"3 0 0 0 1 0 0 0 0 \n",
"4 0 0 0 1 0 0 0 0 \n",
"\n",
" prediction imputation1 \n",
"0 -0.220903 True \n",
"1 -0.219772 True \n",
"2 -0.213418 True \n",
"3 -0.213602 True \n",
"4 -0.212535 True \n",
"\n",
"[5 rows x 105 columns]"
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df.head()"
]
},
{
"cell_type": "code",
"execution_count": 49,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" travel_time prediction travel_time2\n",
"count 5.049000e+06 1.883574e+06 3.165426e+06\n",
"mean 2.395459e+00 7.011203e-02 2.416565e+00\n",
"std 9.192798e-01 1.871515e-01 9.521757e-01\n",
"min 3.364722e-01 -1.735234e+00 3.364722e-01\n",
"25% 1.673816e+00 -3.902411e-02 1.648659e+00\n",
"50% 2.379546e+00 7.028064e-02 2.388763e+00\n",
"75% 3.068053e+00 1.804217e-01 3.113515e+00\n",
"max 5.913699e+00 3.253515e+00 5.913699e+00\n"
]
}
],
"source": [
"print(df[['travel_time','prediction', 'travel_time2']].describe())\n",
"df[['link_ID','date','time_interval_begin','travel_time','imputation1']].to_csv('data/com_trainning.txt',\n",
" header=True,\n",
" index=None,\n",
" sep=';',mode='w')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 构建特征"
]
},
{
"cell_type": "code",
"execution_count": 50,
"metadata": {},
"outputs": [],
"source": [
"df = pd.read_csv('data/com_trainning.txt',\n",
" delimiter=';',\n",
" parse_dates=['time_interval_begin'],\n",
" dtype={'link_ID':object})"
]
},
{
"cell_type": "code",
"execution_count": 51,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>time_interval_begin</th>\n",
" <th>travel_time</th>\n",
" <th>imputation1</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>1.659311</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>1.664941</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>1.671675</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>1.676886</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>1.682314</td>\n",
" <td>True</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID date time_interval_begin travel_time \\\n",
"0 3377906280028510514 2017-03-01 2017-03-01 06:00:00 1.659311 \n",
"1 3377906280028510514 2017-03-01 2017-03-01 06:02:00 1.664941 \n",
"2 3377906280028510514 2017-03-01 2017-03-01 06:04:00 1.671675 \n",
"3 3377906280028510514 2017-03-01 2017-03-01 06:06:00 1.676886 \n",
"4 3377906280028510514 2017-03-01 2017-03-01 06:08:00 1.682314 \n",
"\n",
" imputation1 \n",
"0 True \n",
"1 True \n",
"2 True \n",
"3 True \n",
"4 True "
]
},
"execution_count": 51,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df1 = df.copy()\n",
"df1.head() # imputation1如果是False表示真实值True则是预测"
]
},
{
"cell_type": "code",
"execution_count": 52,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>time_interval_begin</th>\n",
" <th>travel_time</th>\n",
" <th>imputation1</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:10:00</td>\n",
" <td>1.659311</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:12:00</td>\n",
" <td>1.664941</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:14:00</td>\n",
" <td>1.671675</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:16:00</td>\n",
" <td>1.676886</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:18:00</td>\n",
" <td>1.682314</td>\n",
" <td>True</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID date time_interval_begin travel_time \\\n",
"0 3377906280028510514 2017-03-01 2017-03-01 06:10:00 1.659311 \n",
"1 3377906280028510514 2017-03-01 2017-03-01 06:12:00 1.664941 \n",
"2 3377906280028510514 2017-03-01 2017-03-01 06:14:00 1.671675 \n",
"3 3377906280028510514 2017-03-01 2017-03-01 06:16:00 1.676886 \n",
"4 3377906280028510514 2017-03-01 2017-03-01 06:18:00 1.682314 \n",
"\n",
" imputation1 \n",
"0 True \n",
"1 True \n",
"2 True \n",
"3 True \n",
"4 True "
]
},
"execution_count": 52,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#平移5格\n",
"df1['time_interval_begin'] = df1['time_interval_begin'] + pd.DateOffset(minutes=5*2)\n",
"df1.head()"
]
},
{
"cell_type": "code",
"execution_count": 53,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>time_interval_begin</th>\n",
" <th>lagging5</th>\n",
" <th>imputation1</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:10:00</td>\n",
" <td>1.659311</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:12:00</td>\n",
" <td>1.664941</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:14:00</td>\n",
" <td>1.671675</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:16:00</td>\n",
" <td>1.676886</td>\n",
" <td>True</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:18:00</td>\n",
" <td>1.682314</td>\n",
" <td>True</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID date time_interval_begin lagging5 imputation1\n",
"0 3377906280028510514 2017-03-01 2017-03-01 06:10:00 1.659311 True\n",
"1 3377906280028510514 2017-03-01 2017-03-01 06:12:00 1.664941 True\n",
"2 3377906280028510514 2017-03-01 2017-03-01 06:14:00 1.671675 True\n",
"3 3377906280028510514 2017-03-01 2017-03-01 06:16:00 1.676886 True\n",
"4 3377906280028510514 2017-03-01 2017-03-01 06:18:00 1.682314 True"
]
},
"execution_count": 53,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df1 = df1.rename(columns={'travel_time':'lagging'+str(5)})\n",
"df1.head()"
]
},
{
"cell_type": "code",
"execution_count": 54,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>time_interval_begin</th>\n",
" <th>travel_time</th>\n",
" <th>imputation1</th>\n",
" <th>lagging5</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>1.659311</td>\n",
" <td>True</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>1.664941</td>\n",
" <td>True</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>1.671675</td>\n",
" <td>True</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>1.676886</td>\n",
" <td>True</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>1.682314</td>\n",
" <td>True</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:10:00</td>\n",
" <td>1.629241</td>\n",
" <td>False</td>\n",
" <td>1.659311</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:12:00</td>\n",
" <td>1.629241</td>\n",
" <td>False</td>\n",
" <td>1.664941</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:14:00</td>\n",
" <td>1.629241</td>\n",
" <td>False</td>\n",
" <td>1.671675</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID date time_interval_begin travel_time \\\n",
"0 3377906280028510514 2017-03-01 2017-03-01 06:00:00 1.659311 \n",
"1 3377906280028510514 2017-03-01 2017-03-01 06:02:00 1.664941 \n",
"2 3377906280028510514 2017-03-01 2017-03-01 06:04:00 1.671675 \n",
"3 3377906280028510514 2017-03-01 2017-03-01 06:06:00 1.676886 \n",
"4 3377906280028510514 2017-03-01 2017-03-01 06:08:00 1.682314 \n",
"5 3377906280028510514 2017-03-01 2017-03-01 06:10:00 1.629241 \n",
"6 3377906280028510514 2017-03-01 2017-03-01 06:12:00 1.629241 \n",
"7 3377906280028510514 2017-03-01 2017-03-01 06:14:00 1.629241 \n",
"\n",
" imputation1 lagging5 \n",
"0 True NaN \n",
"1 True NaN \n",
"2 True NaN \n",
"3 True NaN \n",
"4 True NaN \n",
"5 False 1.659311 \n",
"6 False 1.664941 \n",
"7 False 1.671675 "
]
},
"execution_count": 54,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df2 = pd.merge(df,df1[['link_ID','time_interval_begin','lagging'+str(5)]],\n",
" on=['link_ID','time_interval_begin'],how='left')\n",
"df2.head(8)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"第5行是第0行前10分钟的值是一样的只是往后移动"
]
},
{
"cell_type": "code",
"execution_count": 55,
"metadata": {},
"outputs": [],
"source": [
"def create_lagging(df, df_original, i):\n",
" df1 = df_original.copy()\n",
" df1['time_interval_begin'] = df1['time_interval_begin']+pd.DateOffset(minutes=i*2)\n",
" df1 = df1.rename(columns={'travel_time':'lagging'+str(i)})\n",
" df2 = pd.merge(df,df1[['link_ID','time_interval_begin','lagging'+str(i)]],\n",
" on=['link_ID','time_interval_begin'],how='left')\n",
" return df2"
]
},
{
"cell_type": "code",
"execution_count": 56,
"metadata": {},
"outputs": [],
"source": [
"df1 = create_lagging(df, df, 1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"构建时间序列特征"
]
},
{
"cell_type": "code",
"execution_count": 57,
"metadata": {},
"outputs": [],
"source": [
"lagging = 5\n",
"for i in range(2,lagging+1):\n",
" df1 = create_lagging(df1,df,i)"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>time_interval_begin</th>\n",
" <th>travel_time</th>\n",
" <th>imputation1</th>\n",
" <th>lagging1</th>\n",
" <th>lagging2</th>\n",
" <th>lagging3</th>\n",
" <th>lagging4</th>\n",
" <th>lagging5</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>1.659311</td>\n",
" <td>True</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>1.664941</td>\n",
" <td>True</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>1.671675</td>\n",
" <td>True</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>1.676886</td>\n",
" <td>True</td>\n",
" <td>1.671675</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>1.682314</td>\n",
" <td>True</td>\n",
" <td>1.676886</td>\n",
" <td>1.671675</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" </tr>\n",
" <tr>\n",
" <th>5</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:10:00</td>\n",
" <td>1.629241</td>\n",
" <td>False</td>\n",
" <td>1.682314</td>\n",
" <td>1.676886</td>\n",
" <td>1.671675</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" </tr>\n",
" <tr>\n",
" <th>6</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:12:00</td>\n",
" <td>1.629241</td>\n",
" <td>False</td>\n",
" <td>1.629241</td>\n",
" <td>1.682314</td>\n",
" <td>1.676886</td>\n",
" <td>1.671675</td>\n",
" <td>1.664941</td>\n",
" </tr>\n",
" <tr>\n",
" <th>7</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:14:00</td>\n",
" <td>1.629241</td>\n",
" <td>False</td>\n",
" <td>1.629241</td>\n",
" <td>1.629241</td>\n",
" <td>1.682314</td>\n",
" <td>1.676886</td>\n",
" <td>1.671675</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID date time_interval_begin travel_time \\\n",
"0 3377906280028510514 2017-03-01 2017-03-01 06:00:00 1.659311 \n",
"1 3377906280028510514 2017-03-01 2017-03-01 06:02:00 1.664941 \n",
"2 3377906280028510514 2017-03-01 2017-03-01 06:04:00 1.671675 \n",
"3 3377906280028510514 2017-03-01 2017-03-01 06:06:00 1.676886 \n",
"4 3377906280028510514 2017-03-01 2017-03-01 06:08:00 1.682314 \n",
"5 3377906280028510514 2017-03-01 2017-03-01 06:10:00 1.629241 \n",
"6 3377906280028510514 2017-03-01 2017-03-01 06:12:00 1.629241 \n",
"7 3377906280028510514 2017-03-01 2017-03-01 06:14:00 1.629241 \n",
"\n",
" imputation1 lagging1 lagging2 lagging3 lagging4 lagging5 \n",
"0 True NaN NaN NaN NaN NaN \n",
"1 True 1.659311 NaN NaN NaN NaN \n",
"2 True 1.664941 1.659311 NaN NaN NaN \n",
"3 True 1.671675 1.664941 1.659311 NaN NaN \n",
"4 True 1.676886 1.671675 1.664941 1.659311 NaN \n",
"5 False 1.682314 1.676886 1.671675 1.664941 1.659311 \n",
"6 False 1.629241 1.682314 1.676886 1.671675 1.664941 \n",
"7 False 1.629241 1.629241 1.682314 1.676886 1.671675 "
]
},
"execution_count": 58,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df1.head(8)"
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [],
"source": [
"link_infos = pd.read_csv('data/gy_contest_link_info.txt',delimiter=';',dtype={'link_ID':object})\n",
"link_tops = pd.read_csv('data/gy_contest_link_top_update.txt',delimiter=',',dtype={'link_ID':object})"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [],
"source": [
"link_tops = link_tops.fillna(0)\n",
"link_infos = pd.merge(link_infos,link_tops,on=['link_ID'],how='left')\n",
"link_infos['links_num'] = link_infos['in_links']+link_infos['out_links']"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [],
"source": [
"link_infos['area'] = link_infos['length'] * link_infos['width']\n",
"df2 = pd.merge(df1,link_infos[['link_ID','length','width',\n",
" 'links_num','area']],on=['link_ID'],how='left')"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>time_interval_begin</th>\n",
" <th>travel_time</th>\n",
" <th>imputation1</th>\n",
" <th>lagging1</th>\n",
" <th>lagging2</th>\n",
" <th>lagging3</th>\n",
" <th>lagging4</th>\n",
" <th>lagging5</th>\n",
" <th>length</th>\n",
" <th>width</th>\n",
" <th>links_num</th>\n",
" <th>area</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>1.659311</td>\n",
" <td>True</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>1.664941</td>\n",
" <td>True</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>1.671675</td>\n",
" <td>True</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>1.676886</td>\n",
" <td>True</td>\n",
" <td>1.671675</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>1.682314</td>\n",
" <td>True</td>\n",
" <td>1.676886</td>\n",
" <td>1.671675</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID date time_interval_begin travel_time \\\n",
"0 3377906280028510514 2017-03-01 2017-03-01 06:00:00 1.659311 \n",
"1 3377906280028510514 2017-03-01 2017-03-01 06:02:00 1.664941 \n",
"2 3377906280028510514 2017-03-01 2017-03-01 06:04:00 1.671675 \n",
"3 3377906280028510514 2017-03-01 2017-03-01 06:06:00 1.676886 \n",
"4 3377906280028510514 2017-03-01 2017-03-01 06:08:00 1.682314 \n",
"\n",
" imputation1 lagging1 lagging2 lagging3 lagging4 lagging5 length \\\n",
"0 True NaN NaN NaN NaN NaN 48 \n",
"1 True 1.659311 NaN NaN NaN NaN 48 \n",
"2 True 1.664941 1.659311 NaN NaN NaN 48 \n",
"3 True 1.671675 1.664941 1.659311 NaN NaN 48 \n",
"4 True 1.676886 1.671675 1.664941 1.659311 NaN 48 \n",
"\n",
" width links_num area \n",
"0 3 2 144 \n",
"1 3 2 144 \n",
"2 3 2 144 \n",
"3 3 2 144 \n",
"4 3 2 144 "
]
},
"execution_count": 62,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df2.head()"
]
},
{
"cell_type": "code",
"execution_count": 63,
"metadata": {},
"outputs": [],
"source": [
"# 假期特征\n",
"df2.loc[df2['date'].isin(['2017-04-02','2017-04-03','2017-04-04','2017-04-29','2017-04-30',\n",
" '2017-05-01','2017-05-28','2017-05-29','2017-05-30']),'vacation']=1\n",
"\n",
"df2.loc[~df2['date'].isin(['2017-04-02','2017-04-03','2017-04-04','2017-04-29','2017-04-30',\n",
" '2017-05-01','2017-05-28','2017-05-29','2017-05-30']),'vacation']=0"
]
},
{
"cell_type": "code",
"execution_count": 64,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>time_interval_begin</th>\n",
" <th>travel_time</th>\n",
" <th>imputation1</th>\n",
" <th>lagging1</th>\n",
" <th>lagging2</th>\n",
" <th>lagging3</th>\n",
" <th>lagging4</th>\n",
" <th>lagging5</th>\n",
" <th>length</th>\n",
" <th>width</th>\n",
" <th>links_num</th>\n",
" <th>area</th>\n",
" <th>vacation</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>1.659311</td>\n",
" <td>True</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>1.664941</td>\n",
" <td>True</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>1.671675</td>\n",
" <td>True</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>1.676886</td>\n",
" <td>True</td>\n",
" <td>1.671675</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>1.682314</td>\n",
" <td>True</td>\n",
" <td>1.676886</td>\n",
" <td>1.671675</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID date time_interval_begin travel_time \\\n",
"0 3377906280028510514 2017-03-01 2017-03-01 06:00:00 1.659311 \n",
"1 3377906280028510514 2017-03-01 2017-03-01 06:02:00 1.664941 \n",
"2 3377906280028510514 2017-03-01 2017-03-01 06:04:00 1.671675 \n",
"3 3377906280028510514 2017-03-01 2017-03-01 06:06:00 1.676886 \n",
"4 3377906280028510514 2017-03-01 2017-03-01 06:08:00 1.682314 \n",
"\n",
" imputation1 lagging1 lagging2 lagging3 lagging4 lagging5 length \\\n",
"0 True NaN NaN NaN NaN NaN 48 \n",
"1 True 1.659311 NaN NaN NaN NaN 48 \n",
"2 True 1.664941 1.659311 NaN NaN NaN 48 \n",
"3 True 1.671675 1.664941 1.659311 NaN NaN 48 \n",
"4 True 1.676886 1.671675 1.664941 1.659311 NaN 48 \n",
"\n",
" width links_num area vacation \n",
"0 3 2 144 0.0 \n",
"1 3 2 144 0.0 \n",
"2 3 2 144 0.0 \n",
"3 3 2 144 0.0 \n",
"4 3 2 144 0.0 "
]
},
"execution_count": 64,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df2.head()"
]
},
{
"cell_type": "code",
"execution_count": 65,
"metadata": {},
"outputs": [],
"source": [
"#起始分钟特征\n",
"df2.loc[df2['time_interval_begin'].dt.hour.isin([6,7,8]),'minute_series']=\\\n",
" df2['time_interval_begin'].dt.minute+(df2['time_interval_begin'].dt.hour-6)*60\n",
"\n",
"df2.loc[df2['time_interval_begin'].dt.hour.isin([13,14,15]),'minute_series']=\\\n",
" df2['time_interval_begin'].dt.minute+(df2['time_interval_begin'].dt.hour-13)*60\n",
"\n",
"df2.loc[df2['time_interval_begin'].dt.hour.isin([16,17,18]),'minute_series']=\\\n",
" df2['time_interval_begin'].dt.minute+(df2['time_interval_begin'].dt.hour-16)*60"
]
},
{
"cell_type": "code",
"execution_count": 66,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>time_interval_begin</th>\n",
" <th>travel_time</th>\n",
" <th>imputation1</th>\n",
" <th>lagging1</th>\n",
" <th>lagging2</th>\n",
" <th>lagging3</th>\n",
" <th>lagging4</th>\n",
" <th>lagging5</th>\n",
" <th>length</th>\n",
" <th>width</th>\n",
" <th>links_num</th>\n",
" <th>area</th>\n",
" <th>vacation</th>\n",
" <th>minute_series</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>1.659311</td>\n",
" <td>True</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>1.664941</td>\n",
" <td>True</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>2.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>1.671675</td>\n",
" <td>True</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>4.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>1.676886</td>\n",
" <td>True</td>\n",
" <td>1.671675</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>6.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>1.682314</td>\n",
" <td>True</td>\n",
" <td>1.676886</td>\n",
" <td>1.671675</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>8.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID date time_interval_begin travel_time \\\n",
"0 3377906280028510514 2017-03-01 2017-03-01 06:00:00 1.659311 \n",
"1 3377906280028510514 2017-03-01 2017-03-01 06:02:00 1.664941 \n",
"2 3377906280028510514 2017-03-01 2017-03-01 06:04:00 1.671675 \n",
"3 3377906280028510514 2017-03-01 2017-03-01 06:06:00 1.676886 \n",
"4 3377906280028510514 2017-03-01 2017-03-01 06:08:00 1.682314 \n",
"\n",
" imputation1 lagging1 lagging2 lagging3 lagging4 lagging5 length \\\n",
"0 True NaN NaN NaN NaN NaN 48 \n",
"1 True 1.659311 NaN NaN NaN NaN 48 \n",
"2 True 1.664941 1.659311 NaN NaN NaN 48 \n",
"3 True 1.671675 1.664941 1.659311 NaN NaN 48 \n",
"4 True 1.676886 1.671675 1.664941 1.659311 NaN 48 \n",
"\n",
" width links_num area vacation minute_series \n",
"0 3 2 144 0.0 0.0 \n",
"1 3 2 144 0.0 2.0 \n",
"2 3 2 144 0.0 4.0 \n",
"3 3 2 144 0.0 6.0 \n",
"4 3 2 144 0.0 8.0 "
]
},
"execution_count": 66,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df2.head()"
]
},
{
"cell_type": "code",
"execution_count": 67,
"metadata": {},
"outputs": [],
"source": [
"# 星期特征\n",
"df2['day_of_week'] = df2['time_interval_begin'].map(lambda x: x.weekday()+1)\n",
"df2.loc[df2['day_of_week'].isin([1,2,3]),'day_of_week_en'] = 1\n",
"df2.loc[df2['day_of_week'].isin([4,5]),'day_of_week_en'] = 2\n",
"df2.loc[df2['day_of_week'].isin([6,7]),'day_of_week_en'] = 3"
]
},
{
"cell_type": "code",
"execution_count": 68,
"metadata": {},
"outputs": [],
"source": [
"# 时间段特征\n",
"df2.loc[df['time_interval_begin'].dt.hour.isin([6,7,8]), 'hour_en']=1\n",
"df2.loc[df['time_interval_begin'].dt.hour.isin([13,14,15]), 'hour_en']=2\n",
"df2.loc[df['time_interval_begin'].dt.hour.isin([16,17,18]), 'hour_en']=3"
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {},
"outputs": [],
"source": [
"# 星期,时间段合并特征\n",
"df2['week_hour'] = df2['day_of_week_en'].astype('str') + ','+df2['hour_en'].astype('str')"
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>time_interval_begin</th>\n",
" <th>travel_time</th>\n",
" <th>imputation1</th>\n",
" <th>lagging1</th>\n",
" <th>lagging2</th>\n",
" <th>lagging3</th>\n",
" <th>lagging4</th>\n",
" <th>lagging5</th>\n",
" <th>length</th>\n",
" <th>width</th>\n",
" <th>links_num</th>\n",
" <th>area</th>\n",
" <th>vacation</th>\n",
" <th>minute_series</th>\n",
" <th>day_of_week</th>\n",
" <th>day_of_week_en</th>\n",
" <th>hour_en</th>\n",
" <th>week_hour</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>1.659311</td>\n",
" <td>True</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>0.0</td>\n",
" <td>3</td>\n",
" <td>1.0</td>\n",
" <td>1.0</td>\n",
" <td>1.0,1.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>1.664941</td>\n",
" <td>True</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>2.0</td>\n",
" <td>3</td>\n",
" <td>1.0</td>\n",
" <td>1.0</td>\n",
" <td>1.0,1.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>1.671675</td>\n",
" <td>True</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>4.0</td>\n",
" <td>3</td>\n",
" <td>1.0</td>\n",
" <td>1.0</td>\n",
" <td>1.0,1.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>1.676886</td>\n",
" <td>True</td>\n",
" <td>1.671675</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>6.0</td>\n",
" <td>3</td>\n",
" <td>1.0</td>\n",
" <td>1.0</td>\n",
" <td>1.0,1.0</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>1.682314</td>\n",
" <td>True</td>\n",
" <td>1.676886</td>\n",
" <td>1.671675</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>48</td>\n",
" <td>3</td>\n",
" <td>2</td>\n",
" <td>144</td>\n",
" <td>0.0</td>\n",
" <td>8.0</td>\n",
" <td>3</td>\n",
" <td>1.0</td>\n",
" <td>1.0</td>\n",
" <td>1.0,1.0</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" link_ID date time_interval_begin travel_time \\\n",
"0 3377906280028510514 2017-03-01 2017-03-01 06:00:00 1.659311 \n",
"1 3377906280028510514 2017-03-01 2017-03-01 06:02:00 1.664941 \n",
"2 3377906280028510514 2017-03-01 2017-03-01 06:04:00 1.671675 \n",
"3 3377906280028510514 2017-03-01 2017-03-01 06:06:00 1.676886 \n",
"4 3377906280028510514 2017-03-01 2017-03-01 06:08:00 1.682314 \n",
"\n",
" imputation1 lagging1 lagging2 lagging3 lagging4 lagging5 length \\\n",
"0 True NaN NaN NaN NaN NaN 48 \n",
"1 True 1.659311 NaN NaN NaN NaN 48 \n",
"2 True 1.664941 1.659311 NaN NaN NaN 48 \n",
"3 True 1.671675 1.664941 1.659311 NaN NaN 48 \n",
"4 True 1.676886 1.671675 1.664941 1.659311 NaN 48 \n",
"\n",
" width links_num area vacation minute_series day_of_week \\\n",
"0 3 2 144 0.0 0.0 3 \n",
"1 3 2 144 0.0 2.0 3 \n",
"2 3 2 144 0.0 4.0 3 \n",
"3 3 2 144 0.0 6.0 3 \n",
"4 3 2 144 0.0 8.0 3 \n",
"\n",
" day_of_week_en hour_en week_hour \n",
"0 1.0 1.0 1.0,1.0 \n",
"1 1.0 1.0 1.0,1.0 \n",
"2 1.0 1.0 1.0,1.0 \n",
"3 1.0 1.0 1.0,1.0 \n",
"4 1.0 1.0 1.0,1.0 "
]
},
"execution_count": 70,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df2.head()"
]
},
{
"cell_type": "code",
"execution_count": 71,
"metadata": {},
"outputs": [],
"source": [
"df2 = pd.get_dummies(df2,columns=['week_hour','links_num','width'])"
]
},
{
"cell_type": "code",
"execution_count": 72,
"metadata": {},
"outputs": [],
"source": [
"def mean_time(group):\n",
" group['link_ID_en'] = group['travel_time'].mean()\n",
" return group"
]
},
{
"cell_type": "code",
"execution_count": 73,
"metadata": {},
"outputs": [],
"source": [
"df2 = df2.groupby('link_ID').apply(mean_time)"
]
},
{
"cell_type": "code",
"execution_count": 74,
"metadata": {},
"outputs": [],
"source": [
"sorted_link = np.sort(df2['link_ID_en'].unique())\n",
"df2['link_ID_en'] = df2['link_ID_en'].map(lambda x: np.argmin(x >= sorted_link))"
]
},
{
"cell_type": "code",
"execution_count": 75,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>link_ID</th>\n",
" <th>date</th>\n",
" <th>time_interval_begin</th>\n",
" <th>travel_time</th>\n",
" <th>imputation1</th>\n",
" <th>lagging1</th>\n",
" <th>lagging2</th>\n",
" <th>lagging3</th>\n",
" <th>lagging4</th>\n",
" <th>lagging5</th>\n",
" <th>...</th>\n",
" <th>links_num_2</th>\n",
" <th>links_num_3</th>\n",
" <th>links_num_4</th>\n",
" <th>links_num_5</th>\n",
" <th>width_3</th>\n",
" <th>width_6</th>\n",
" <th>width_9</th>\n",
" <th>width_12</th>\n",
" <th>width_15</th>\n",
" <th>link_ID_en</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:00:00</td>\n",
" <td>1.659311</td>\n",
" <td>True</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>...</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>47</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:02:00</td>\n",
" <td>1.664941</td>\n",
" <td>True</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>...</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>47</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:04:00</td>\n",
" <td>1.671675</td>\n",
" <td>True</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>...</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>47</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:06:00</td>\n",
" <td>1.676886</td>\n",
" <td>True</td>\n",
" <td>1.671675</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>NaN</td>\n",
" <td>...</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>47</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>3377906280028510514</td>\n",
" <td>2017-03-01</td>\n",
" <td>2017-03-01 06:08:00</td>\n",
" <td>1.682314</td>\n",
" <td>True</td>\n",
" <td>1.676886</td>\n",
" <td>1.671675</td>\n",
" <td>1.664941</td>\n",
" <td>1.659311</td>\n",
" <td>NaN</td>\n",
" <td>...</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>1</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>0</td>\n",
" <td>47</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>5 rows × 36 columns</p>\n",
"</div>"
],
"text/plain": [
" link_ID date time_interval_begin travel_time \\\n",
"0 3377906280028510514 2017-03-01 2017-03-01 06:00:00 1.659311 \n",
"1 3377906280028510514 2017-03-01 2017-03-01 06:02:00 1.664941 \n",
"2 3377906280028510514 2017-03-01 2017-03-01 06:04:00 1.671675 \n",
"3 3377906280028510514 2017-03-01 2017-03-01 06:06:00 1.676886 \n",
"4 3377906280028510514 2017-03-01 2017-03-01 06:08:00 1.682314 \n",
"\n",
" imputation1 lagging1 lagging2 lagging3 lagging4 lagging5 ... \\\n",
"0 True NaN NaN NaN NaN NaN ... \n",
"1 True 1.659311 NaN NaN NaN NaN ... \n",
"2 True 1.664941 1.659311 NaN NaN NaN ... \n",
"3 True 1.671675 1.664941 1.659311 NaN NaN ... \n",
"4 True 1.676886 1.671675 1.664941 1.659311 NaN ... \n",
"\n",
" links_num_2 links_num_3 links_num_4 links_num_5 width_3 width_6 \\\n",
"0 1 0 0 0 1 0 \n",
"1 1 0 0 0 1 0 \n",
"2 1 0 0 0 1 0 \n",
"3 1 0 0 0 1 0 \n",
"4 1 0 0 0 1 0 \n",
"\n",
" width_9 width_12 width_15 link_ID_en \n",
"0 0 0 0 47 \n",
"1 0 0 0 47 \n",
"2 0 0 0 47 \n",
"3 0 0 0 47 \n",
"4 0 0 0 47 \n",
"\n",
"[5 rows x 36 columns]"
]
},
"execution_count": 75,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df2.head()"
]
},
{
"cell_type": "code",
"execution_count": 76,
"metadata": {},
"outputs": [],
"source": [
"df2.to_csv('data/trainning.txt',header=True,index=None,sep=';',mode='w')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}