# features計算過程紀錄
這份檔案用於紀錄各資料在資料處理中各階段的命名規則,避免過多版本時混淆。
## 資料存放位置
[onedrive](https://1drv.ms/f/c/002d06ef873e3a00/EkeOXSUEem1Op399ZprSGbEBdspHKfZaxtVDORlChXFuDg?e=KAHVxe)
## 資料版本定義
### 舉例
{數字:代表版本號,所有檔案按照此順序處理}. {檔案名稱}
- {這個版本的檔案內容描述,包含簡述與欄位。}
---
1. 我是檔名
- 我是描述。
---
### VD
1. merged_VD_all(原)
- 從官網上抓下來的原始資料,未經任何處理直接合併為單個檔案。
- 欄位:`VDID, DataCollectTime, LinkID, LaneID, LaneType, Speed, Occupancy, VehicleType, Volume, VehicleSpeed`
- `DataCollectTime`的`type`為`string`
- freq:1分鐘一筆
2. vd_pre(原)
- 只包含需要的日期跟VDID
- 欄位:`VDID, DataCollectTime, LinkID, LaneID, LaneType, Speed, Occupancy, VehicleType, Volume, VehicleSpeed`
- 包含缺失值(-99)
- `DataCollectTime`的`type`為`datetime64[ns]`
3. vd_pre_no_-99_value(原)
- 同`vd_pre`,但已經把`Speed, Occupancy, Volume, VehicleSpeed`中`-99`的數值設為`nan`
4. vd_pre_no_-99_no_dul(原)
- 同`vd_pre_no_-99_value`,但刪除完全重複的row:透過對每個row計算hash,再根據hash刪除相同的row.
- 多了一個欄位:`row_hash`
- hash key: `0123456789abcdef`
- type: `uint64`
5. vd_pre_5min(原)
- 同`vd_pre_no_-99_no_dul`
- 但把時間改為5分鐘1筆:假設時間為`1, 2, 3, 4, 5`,轉換成`5, 5, 5, 5, 5`。
- 新時間欄位直接取代舊時間欄位(`DataCollectTime`)
6. vd_features_v1(原)
1. vd_features_v1_spdavg
- 欄位: `VDID, timestamp, weighted_avg`
- 根據`vd_pre_5min`計算出`spdavg`
2. vd_features_v1_spdtrnd
- 欄位: `VDID, timestamp, speed_diff`
- 根據`vd_pre_5min`計算出`spdtrnd`
3. vd_features_v1_occ
- 欄位: `VDID, timestamp, occ`
- 根據`vd_pre_5min`計算出`occ`
- pandas df
- 欄位:`VDID, timestamp, spdavg, spdtrnd, occ`
- 合併`6-1~6-3`後得到`vd_features_v1`.
7. vd_features_v1_flat(原)
- pandas df
- 把`vd_features_v1`展平,columns為`timestamp`, `feature_name * VDID`.
- 欄位照:先`feature(spdavg, spdtrnd, occ)`,後`VDID`,由左至右排序。格式為`feature_VDID`,ex: `weighted_avg_VD-N1-N-18.010-M-LOOP`
<!-- 8. vd_features_v1_flat_no_missed
- 同`vd_features_v1_flat`,但把所有缺失的時間都補上,value為nan。
- ex: `20240101 00:30`在日期區間內,但`vd_pre_5min`找不到任何該時間的資料,則補上。 -->
### m05
1. merged_m05_all(原)
- 從官網上抓下來的原始資料,未經任何處理直接合併為單個檔案。
- 欄位:`DataCollectTime`, `GantryFrom`, `GantryTo`, `VehicleType`, `Speed`, `Volume`
- `DataCollectTime`的`type`為`string`
- `GantryFrom`, `GantryTo`可能經過篩選,細節不明。
- freq:5分鐘一筆
2. m05_pre(原)
- 只包含需要的日期跟GantryID(GantryTo, GantryFrom)
- 欄位:`DataCollectTime`, `GantryFrom`, `GantryTo`, `VehicleType`, `Speed`, `Volume`
- `DataCollectTime`的`type`為`datetime64[ns]`
3. m05_features_v1_spdavg(原)
- pandas df
- 根據m05_pre計算出spdavg
- 欄位:`timestamp`, `GantryFrom`, `GantryTo`, `weighted_avg`
4. m05_specific_route_spdavg_flat_with_state
- pandas df
- 把`m05_features_v1_spdavg`展平,columns為`timestamp`, `spdavg * gantryIDs`. `gantryIDs`為一組門架代號,由兩個門架ID組成,格式為`GantryFrom-GantryTo`,ex: `01F0213N-01F0155N`.
- 欄位照:<!-- 先`feature(spdavg)`,後 -->`gantryIDs`,由左至右排序。格式為`m05_spdavg_gantryIDs`,ex: `weighted_avg_01F0155S-01F0182S`
- 從m05_features_v1_spdvag 取出我們要的路段('01F0248S', '01F0264S')後 算state, ttc, ttf 並改欄位名稱為 01F0248S_01F0264S_spdavg
- 刪除假日資料
### m06
1. M06A_months_parquet(原)
- 內含12個檔名為`M06A_1.parquet`, `M06A_2.parquet`, ..., `M06A_12.parquet`的檔案,每個代表一個月分,合起來為2024年`m06a`的原始檔案parquet.
- 欄位:`VehicleType`, `DetectionTimeO`, `GantryO`, `DetectionTimeD`, `GantryD`, `TripLength`, `TripEnd`, `Route`
- 其中`DetectionTimeO`, `DetectionTimeD`的`type`為`str`
1. M06A_25100_S_up(原)
- 代表篩選`M06A_months_parquet`中從南下(S)方向上(up)位於25.100K的交流道(台北交流道)的所有m06紀錄。
- 為整年份的檔案,未按月分檔。
- 25100代表交流道里程數,單位為m.
- S代表南下或北上方向(N)。
- up代表上交流道或下交流道(down)。
- 另有`M06A_25100_S_down.parquet`, `M06A_25100_N_up.parquet`, `M06A_25100_N_down.parquet`
- 時間精確到秒
- 欄位:`VehicleType`, `DetectionTimeO`, `GantryO`, `DetectionTimeD`, `GantryD`, `TripLength`, `TripEnd`, `Route`
- 其中`DetectionTimeO`, `DetectionTimeD`的`type`為`str`
- `dask`
2. M06A_25100_S_up_count(原)
- 命名規則同`M06A_25100_S_up`,但記錄的是`groupby('DetectionTimeO').size()`或`groupby('DetectionTimeD').size()`.
- 欄位:`DetectionTime`, `count`.
- 其中`DetectionTime`的`type`為`datetime64[ns]`
- 時間精確到5分鐘,轉換規則為:假設時間為`1, 2, 3, 4, 5`,轉換成`5, 5, 5, 5, 5`,忽略秒數,只看分鐘。
- 另有`M06A_25100_S_down_count.parquet`, `M06A_25100_N_up_count.parquet`, `M06A_25100_N_down_count.parquet`.
- 篩除`DetectionTime`晚於`2024-12-31 23:55:00`或早於`2024-01-01 00:00:00`的資料。
- 資料為每5分鐘一筆,若無資料的時間自動把value設為0。
- `pandas`
3. M06A_25100_S_up_loc(原)
- 同`M06A_25100_S_up_count`,但本資料是計算`groupby('GantryO').size()`或`groupby('GantryD').size()`
- 欄位:`Gantry`, `count`
2. M06A_pre(原)
- 只篩選出在`Route`中有包含需要門架(gantryID_v1)中的任何一個門架的紀錄
- 欄位:`VehicleType`, `DetectionTimeO`, `GantryO`, `DetectionTimeD`, `GantryD`, `TripLength`, `TripEnd`, `Route`
- 其中`DetectionTimeO`, `DetectionTimeD`的type為`datetime64[ns]`
3. M06A_extract(原)
- 把`Route`欄位的value按照需要門架(gantryID_v1)中的GantryID解析出時間,欄位名稱為`time_{GantryID}`, type為`datetime64[ns]`, ex: `time_01F0293N`.
- 欄位:`Route`, `VehicleType`, `TripLength`, `time_{GantryID 1}`, ...
4. M06A_avgspeed_{GantryID 1}-{GantryID 2}(原)
- pandas df
- 從GantryID 1到GantryID 2平均行車速度
- 平均為每5min為一個時間區間,塞選其中符合條件的資料計算。
- 以endtime(GantryID 2的時間)決定屬於哪個時間區間。
- 假設時間為`1, 2, 3, 4, 5`,轉換成`5, 5, 5, 5, 5`。
- 欄位: `m06_avgspeed`, `timestamp`
5. M06A_feat_{GantryID 1}-{GantryID 2}(原)
- 欄位: `timestamp`, `m06_state`, `m06_ttf`, `m06_ttc`, `m06_tag`
- 計算traffic state、ttc、ttf(目前按照論文定義)。
- tag用於標示是否為`traffic state`(`m06_state`)狀態轉換的前後30分鐘。
<!-- ### 門架靜態資料
1. etag_distance
- 來自eTag 配對路徑靜態資訊(v2.0),有各相鄰門架間的距離。 -->
## 合併成訓練資料
1. merged_37(原)
- pandas df
- 把`vd_features_v1_flat`、`m05_features_v1_flat`、`M06A_feat_01F0248S-01F0264S`根據時間合併。
- 以上三個檔案分別只讀取並使用以下欄位:
- vd: `['VD-N1-S-23.900-M-LOOP', 'VD-N1-S-24.400-M-RS',
'VD-N1-S-25.440-N-LOOP', 'VD-N1-S-25.850-M-LOOP',
'VD-N1-S-26.350-M-RS', 'VD-N1-S-26.750-N-LOOP',
'VD-N1-S-28.840-M-RS']`的`['spdavg', 'spdtrnd', 'occ']`
- m05: `['m05_spdavg_01F0248S-01F0264S']`
- m06: `['m06_state', 'm06_ttf', 'm06_ttc', 'm06_ttf_no_upbound', 'm06_tag']`
- 若有缺失值(nan),使用向前填充(`bfill`,例如0, nan, 9變成0, 9, 9)。
- 只篩選出時間在`2024-01-01 00:00:00`~`2024-12-31 23:59:59`,並確保每個時間都沒有nan.
- 篩除週末,只保留週一到週五。
- 計算traffic state、ttc、ttf、tag
- 欄位:[`spdavg_VD-N1-S-23.900-M-LOOP`,`spdtrnd_VD-N1-S-23.900-M-LOOP`,`occ_VD-N1-S-23.900-M-LOOP`,`spdavg_VD-N1-S-24.400-M-RS`,`spdtrnd_VD-N1-S-24.400-M-RS`,`occ_VD-N1-S-24.400-M-RS`,`spdavg_VD-N1-S-25.440-N-LOOP`,`spdtrnd_VD-N1-S-25.440-N-LOOP`,`occ_VD-N1-S-25.440-N-LOOP`,`spdavg_VD-N1-S-25.850-M-LOOP`,`spdtrnd_VD-N1-S-25.850-M-LOOP`,`occ_VD-N1-S-25.850-M-LOOP`,`spdavg_VD-N1-S-26.350-M-RS`,`spdtrnd_VD-N1-S-26.350-M-RS`,`occ_VD-N1-S-26.350-M-RS`,`spdavg_VD-N1-S-26.750-N-LOOP`,`spdtrnd_VD-N1-S-26.750-N-LOOP`,`occ_VD-N1-S-26.750-N-LOOP`,`spdavg_VD-N1-S-28.840-M-RS`,`spdtrnd_VD-N1-S-28.840-M-RS`,`occ_VD-N1-S-28.840-M-RS`,`m05_spdavg_01F0248S-01F0264S`,`m06_ttf`,`m06_ttc`,`m06_tag`]
- index: 時間,`type`為`datetime64[ns]`
2. merged_37_5-10
* 從 merged_37 改,刪除 22.~5. 的資料
3. merged_m05_weekdays_only
- 將vd 與 m05_flat_state 合併
- 刪除假日資料
4. merged_37_with_bins.csv
* from: merged_37
* 依照 m05_spdavg_01F0248S-01F0264S,每 20 km 編號 (start from 0)
5. merged_37_cleaned
- 將手動填充上去的資料刪除
6. merged_m06_m05
- 把m06 和 merged_m05_weekdays_only 合併
7. merged_37_state(原)
- 與`merged_37`相同,但增加traffic state欄位(名稱:`m06_state`)
- 欄位:`spdavg_VD-N1-S-23.900-M-LOOP`,`spdtrnd_VD-N1-S-23.900-M-LOOP`,`occ_VD-N1-S-23.900-M-LOOP`,`spdavg_VD-N1-S-24.400-M-RS`,`spdtrnd_VD-N1-S-24.400-M-RS`,`occ_VD-N1-S-24.400-M-RS`,`spdavg_VD-N1-S-25.440-N-LOOP`,`spdtrnd_VD-N1-S-25.440-N-LOOP`,`occ_VD-N1-S-25.440-N-LOOP`,`spdavg_VD-N1-S-25.850-M-LOOP`,`spdtrnd_VD-N1-S-25.850-M-LOOP`,`occ_VD-N1-S-25.850-M-LOOP`,`spdavg_VD-N1-S-26.350-M-RS`,`spdtrnd_VD-N1-S-26.350-M-RS`,`occ_VD-N1-S-26.350-M-RS`,`spdavg_VD-N1-S-26.750-N-LOOP`,`spdtrnd_VD-N1-S-26.750-N-LOOP`,`occ_VD-N1-S-26.750-N-LOOP`,`spdavg_VD-N1-S-28.840-M-RS`,`spdtrnd_VD-N1-S-28.840-M-RS`,`occ_VD-N1-S-28.840-M-RS`,`m05_spdavg_01F0248S-01F0264S`,`m06_state`,`m06_ttf`,`m06_ttc`,`m06_tag`
8. merged_37_plot
- 與`merged_37_state`相同,但增加沒有上限的ttf欄位(名稱:`m06_ttf_no_upbound`),該欄位為未經"把超過37的設為37"處理,可用於分析平均塞車時間。
## 參數定義
gantryID_v1:
```
gantry_id = ['01F0293N', '01F0256N', '01F0233N', '01F0213N',
'01F0293S', '01F0264S', '01F0248S', '01F0182S']