diff --git a/Analysis/0109_preprocess/0122_preprocess_9.5.ipynb b/Analysis/0109_preprocess/0122_preprocess_9.5.ipynb
new file mode 100644
index 000000000..f965c317a
--- /dev/null
+++ b/Analysis/0109_preprocess/0122_preprocess_9.5.ipynb
@@ -0,0 +1,8793 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import os\n",
+ "import sumolib\n",
+ "import random\n",
+ "from tqdm import tqdm\n",
+ "from datetime import datetime"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# A. 이동류 매칭"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " 0%| | 0/17280 [00:00, ?it/s]"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "100%|██████████| 17280/17280 [00:13<00:00, 1294.28it/s]\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " move_A | \n",
+ " move_B | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 7 | \n",
+ " 3 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 6 | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 6 | \n",
+ " 2 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 5 | \n",
+ " 2 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 176 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 8 | \n",
+ " 3 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 176 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 5 | \n",
+ " 18 | \n",
+ "
\n",
+ " \n",
+ " 8 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ " 9 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 7 | \n",
+ " 3 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phas_A phas_B move_A move_B\n",
+ "0 175 1 1 8 4\n",
+ "1 175 2 2 7 3\n",
+ "2 175 3 3 6 1\n",
+ "3 175 3 4 6 2\n",
+ "4 175 4 4 5 2\n",
+ "5 176 1 1 8 4\n",
+ "6 176 2 2 8 3\n",
+ "7 176 3 3 5 18\n",
+ "8 177 1 1 8 4\n",
+ "9 177 2 2 7 3"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# [이동류번호] 불러오기 (약 1분의 소요시간)\n",
+ "path_moves = '../../Data/tables/moves/'\n",
+ "csv_moves = os.listdir('../../Data/tables/moves/')\n",
+ "moves = [pd.read_csv(path_moves + csv_move, index_col=0) for csv_move in tqdm(csv_moves)]\n",
+ "match1 = pd.concat(moves).drop_duplicates().sort_values(by=['inter_no','phas_A','phas_B']).reset_index(drop=True)\n",
+ "match1.head(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ "
\n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 2 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no\n",
+ "0 175 1 A 8\n",
+ "0 175 1 B 4\n",
+ "1 175 2 A 7\n",
+ "1 175 2 B 3\n",
+ "2 175 3 A 6\n",
+ "2 175 3 B 1\n",
+ "4 175 4 A 5\n",
+ "3 175 4 B 2\n",
+ "5 176 1 A 8\n",
+ "5 176 1 B 4"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# 계층화 (inter_no, phas_A, phas_B, move_A, move_B) -> ('inter_no', 'phase_no', 'ring_type', 'move_no')\n",
+ "matchA = match1[['inter_no', 'phas_A', 'move_A']].copy()\n",
+ "matchA.columns = ['inter_no', 'phase_no', 'move_no']\n",
+ "matchA['ring_type'] = 'A'\n",
+ "matchB = match1[['inter_no', 'phas_B', 'move_B']].copy()\n",
+ "matchB.columns = ['inter_no', 'phase_no', 'move_no']\n",
+ "matchB['ring_type'] = 'B'\n",
+ "match2 = pd.concat([matchA, matchB]).drop_duplicates()\n",
+ "match2 = match2[['inter_no', 'phase_no', 'ring_type', 'move_no']]\n",
+ "match2 = match2.sort_values(by=list(match2.columns))\n",
+ "match2.head(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 8 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 9 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 10 | \n",
+ " 176 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 11 | \n",
+ " 176 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 12 | \n",
+ " 176 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 13 | \n",
+ " 176 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 14 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 15 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 16 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 17 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 18 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 19 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 20 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 21 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 22 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 23 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 24 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 25 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 26 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 27 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 28 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 29 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 30 | \n",
+ " 201 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 31 | \n",
+ " 201 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 32 | \n",
+ " 201 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 33 | \n",
+ " 201 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 34 | \n",
+ " 201 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 35 | \n",
+ " 201 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 36 | \n",
+ " 201 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 37 | \n",
+ " 201 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 38 | \n",
+ " 201 | \n",
+ " 5 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 39 | \n",
+ " 201 | \n",
+ " 5 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 40 | \n",
+ " 202 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 41 | \n",
+ " 202 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 42 | \n",
+ " 202 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 43 | \n",
+ " 202 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 44 | \n",
+ " 206 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 45 | \n",
+ " 206 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 46 | \n",
+ " 206 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 47 | \n",
+ " 206 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 48 | \n",
+ " 206 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 49 | \n",
+ " 206 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 50 | \n",
+ " 206 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 51 | \n",
+ " 206 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 52 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 53 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 54 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 55 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 56 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 57 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 58 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 59 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir\n",
+ "0 175 1 A 8 남 북\n",
+ "1 175 1 B 4 북 남\n",
+ "2 175 2 A 7 북 동\n",
+ "3 175 2 B 3 남 서\n",
+ "4 175 3 A 6 동 서\n",
+ "5 175 3 B 1 동 남\n",
+ "6 175 4 A 5 서 북\n",
+ "7 175 4 B 2 서 동\n",
+ "8 176 1 A 8 남 북\n",
+ "9 176 1 B 4 북 남\n",
+ "10 176 2 A 8 남 북\n",
+ "11 176 2 B 3 남 서\n",
+ "12 176 3 A 5 서 북\n",
+ "13 176 3 B 18 NaN NaN\n",
+ "14 177 1 A 8 남 북\n",
+ "15 177 1 B 4 북 남\n",
+ "16 177 2 A 7 북 동\n",
+ "17 177 2 B 3 남 서\n",
+ "18 177 3 A 17 NaN NaN\n",
+ "19 177 3 B 18 NaN NaN\n",
+ "20 177 4 A 5 서 북\n",
+ "21 177 4 B 1 동 남\n",
+ "22 178 1 A 8 남 북\n",
+ "23 178 1 B 4 북 남\n",
+ "24 178 2 A 7 북 동\n",
+ "25 178 2 B 3 남 서\n",
+ "26 178 3 A 5 서 북\n",
+ "27 178 3 B 2 서 동\n",
+ "28 178 4 A 6 동 서\n",
+ "29 178 4 B 1 동 남\n",
+ "30 201 1 A 8 남 북\n",
+ "31 201 1 B 3 남 서\n",
+ "32 201 2 A 5 서 북\n",
+ "33 201 2 B 2 서 동\n",
+ "34 201 3 A 6 동 서\n",
+ "35 201 3 B 2 서 동\n",
+ "36 201 4 A 6 동 서\n",
+ "37 201 4 B 1 동 남\n",
+ "38 201 5 A 7 북 동\n",
+ "39 201 5 B 4 북 남\n",
+ "40 202 1 A 6 동 서\n",
+ "41 202 1 B 2 서 동\n",
+ "42 202 2 A 17 NaN NaN\n",
+ "43 202 2 B 18 NaN NaN\n",
+ "44 206 1 A 8 남 북\n",
+ "45 206 1 B 4 북 남\n",
+ "46 206 2 A 17 NaN NaN\n",
+ "47 206 2 B 18 NaN NaN\n",
+ "48 206 3 A 8 남 북\n",
+ "49 206 3 B 4 북 남\n",
+ "50 206 4 A 17 NaN NaN\n",
+ "51 206 4 B 18 NaN NaN\n",
+ "52 210 1 A 6 동 서\n",
+ "53 210 1 B 18 NaN NaN\n",
+ "54 210 2 A 5 서 북\n",
+ "55 210 2 B 2 서 동\n",
+ "56 210 3 A 7 북 동\n",
+ "57 210 3 B 4 북 남\n",
+ "58 210 4 A 8 남 북\n",
+ "59 210 4 B 3 남 서"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# [nema 이동류목록] 불러오기 및 병합\n",
+ "nema = pd.read_csv('../../Data/tables/nema.csv', encoding='cp949')\n",
+ "match3 = pd.merge(match2, nema, how='left', on='move_no').drop_duplicates()\n",
+ "match3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 179 | \n",
+ " 004 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 003 | \n",
+ " 176 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 001 | \n",
+ " 095 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 179 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 8 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 9 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 359 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 10 | \n",
+ " 176 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 11 | \n",
+ " 176 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 12 | \n",
+ " 176 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 356 | \n",
+ "
\n",
+ " \n",
+ " 13 | \n",
+ " 176 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 14 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 15 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 001 | \n",
+ " 176 | \n",
+ "
\n",
+ " \n",
+ " 16 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 17 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 179 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 18 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 19 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 20 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 21 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 22 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 23 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 24 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 25 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 26 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 27 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 28 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 29 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 30 | \n",
+ " 201 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 31 | \n",
+ " 201 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 32 | \n",
+ " 201 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 33 | \n",
+ " 201 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 34 | \n",
+ " 201 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 35 | \n",
+ " 201 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 36 | \n",
+ " 201 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 37 | \n",
+ " 201 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 38 | \n",
+ " 201 | \n",
+ " 5 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 39 | \n",
+ " 201 | \n",
+ " 5 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 40 | \n",
+ " 202 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 41 | \n",
+ " 202 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 42 | \n",
+ " 202 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 43 | \n",
+ " 202 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 44 | \n",
+ " 206 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 45 | \n",
+ " 206 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 46 | \n",
+ " 206 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 47 | \n",
+ " 206 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 48 | \n",
+ " 206 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 49 | \n",
+ " 206 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 50 | \n",
+ " 206 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 51 | \n",
+ " 206 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 52 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 53 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 54 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 55 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 56 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 359 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 57 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 58 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 59 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle\n",
+ "0 175 1 A 8 남 북 179 004\n",
+ "1 175 1 B 4 북 남 003 176\n",
+ "2 175 2 A 7 북 동 001 095\n",
+ "3 175 2 B 3 남 서 179 270\n",
+ "4 175 3 A 6 동 서 090 270\n",
+ "5 175 3 B 1 동 남 090 180\n",
+ "6 175 4 A 5 서 북 268 000\n",
+ "7 175 4 B 2 서 동 270 090\n",
+ "8 176 1 A 8 남 북 180 000\n",
+ "9 176 1 B 4 북 남 359 180\n",
+ "10 176 2 A 8 남 북 180 000\n",
+ "11 176 2 B 3 남 서 180 270\n",
+ "12 176 3 A 5 서 북 270 356\n",
+ "13 176 3 B 18 NaN NaN NaN NaN\n",
+ "14 177 1 A 8 남 북 180 000\n",
+ "15 177 1 B 4 북 남 001 176\n",
+ "16 177 2 A 7 북 동 000 090\n",
+ "17 177 2 B 3 남 서 179 270\n",
+ "18 177 3 A 17 NaN NaN NaN NaN\n",
+ "19 177 3 B 18 NaN NaN NaN NaN\n",
+ "20 177 4 A 5 서 북 268 000\n",
+ "21 177 4 B 1 동 남 090 180\n",
+ "22 178 1 A 8 남 북 180 000\n",
+ "23 178 1 B 4 북 남 000 180\n",
+ "24 178 2 A 7 북 동 000 090\n",
+ "25 178 2 B 3 남 서 180 270\n",
+ "26 178 3 A 5 서 북 270 000\n",
+ "27 178 3 B 2 서 동 270 090\n",
+ "28 178 4 A 6 동 서 090 270\n",
+ "29 178 4 B 1 동 남 090 180\n",
+ "30 201 1 A 8 남 북 180 000\n",
+ "31 201 1 B 3 남 서 180 270\n",
+ "32 201 2 A 5 서 북 270 000\n",
+ "33 201 2 B 2 서 동 270 090\n",
+ "34 201 3 A 6 동 서 090 270\n",
+ "35 201 3 B 2 서 동 270 090\n",
+ "36 201 4 A 6 동 서 090 270\n",
+ "37 201 4 B 1 동 남 090 180\n",
+ "38 201 5 A 7 북 동 000 090\n",
+ "39 201 5 B 4 북 남 000 180\n",
+ "40 202 1 A 6 동 서 090 270\n",
+ "41 202 1 B 2 서 동 270 090\n",
+ "42 202 2 A 17 NaN NaN NaN NaN\n",
+ "43 202 2 B 18 NaN NaN NaN NaN\n",
+ "44 206 1 A 8 남 북 180 000\n",
+ "45 206 1 B 4 북 남 000 180\n",
+ "46 206 2 A 17 NaN NaN NaN NaN\n",
+ "47 206 2 B 18 NaN NaN NaN NaN\n",
+ "48 206 3 A 8 남 북 180 000\n",
+ "49 206 3 B 4 북 남 000 180\n",
+ "50 206 4 A 17 NaN NaN NaN NaN\n",
+ "51 206 4 B 18 NaN NaN NaN NaN\n",
+ "52 210 1 A 6 동 서 090 270\n",
+ "53 210 1 B 18 NaN NaN NaN NaN\n",
+ "54 210 2 A 5 서 북 268 000\n",
+ "55 210 2 B 2 서 동 270 090\n",
+ "56 210 3 A 7 북 동 359 090\n",
+ "57 210 3 B 4 북 남 000 180\n",
+ "58 210 4 A 8 남 북 180 000\n",
+ "59 210 4 B 3 남 서 180 270"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# [방위각정보] 불러오기, 계층화, 병합\n",
+ "# 불러오기\n",
+ "dtype_dict = {f'angle_{alph}{j}':'str' for alph in ['A', 'B'] for j in range(1,9)}\n",
+ "angle_original = pd.read_csv('../../Data/tables/angle.csv', index_col=0, dtype = dtype_dict)\n",
+ "# 계층화\n",
+ "angle = []\n",
+ "for i, row in angle_original.iterrows():\n",
+ " angle_codes = row[[f'angle_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " new = pd.DataFrame({'inter_no':[row.inter_no] * 16, 'phase_no':list(range(1, 9))*2, 'ring_type':['A'] * 8 + ['B'] * 8, 'angle_code':angle_codes.to_list()})\n",
+ " angle.append(new)\n",
+ "angle = pd.concat(angle)\n",
+ "angle = angle.dropna().reset_index(drop=True)\n",
+ "# 병합\n",
+ "six_chars = angle.angle_code.apply(lambda x:len(x)==6)\n",
+ "angle.loc[six_chars,'inc_angle'] = angle.angle_code.apply(lambda x:x[:3])\n",
+ "angle.loc[six_chars,'out_angle'] = angle.angle_code.apply(lambda x:x[3:])\n",
+ "angle = angle.drop('angle_code', axis=1)\n",
+ "match4 = pd.merge(match3, angle, how='left', left_on=['inter_no', 'phase_no', 'ring_type'],\n",
+ " right_on=['inter_no', 'phase_no', 'ring_type']).drop_duplicates()\n",
+ "match4"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 179 | \n",
+ " 004 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 003 | \n",
+ " 176 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 001 | \n",
+ " 095 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 179 | \n",
+ " 270 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 8 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " -571542810_01 | \n",
+ " -571542797_02.99 | \n",
+ " i1 | \n",
+ "
\n",
+ " \n",
+ " 9 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 359 | \n",
+ " 180 | \n",
+ " 571542797_02.99 | \n",
+ " 571542810_01 | \n",
+ " i1 | \n",
+ "
\n",
+ " \n",
+ " 10 | \n",
+ " 176 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " -571542810_01 | \n",
+ " -571542797_02.99 | \n",
+ " i1 | \n",
+ "
\n",
+ " \n",
+ " 11 | \n",
+ " 176 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " -571542810_01 | \n",
+ " 571543469_01 | \n",
+ " i1 | \n",
+ "
\n",
+ " \n",
+ " 12 | \n",
+ " 176 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 356 | \n",
+ " 571543469_02 | \n",
+ " -571542797_02.99 | \n",
+ " i1 | \n",
+ "
\n",
+ " \n",
+ " 13 | \n",
+ " 176 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i1 | \n",
+ "
\n",
+ " \n",
+ " 14 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " -571542809_01 | \n",
+ " 571542811_01 | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 15 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 001 | \n",
+ " 176 | \n",
+ " 571542811_02 | \n",
+ " 571542809_01 | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 16 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ " 571542811_02 | \n",
+ " 571542107_01 | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 17 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 179 | \n",
+ " 270 | \n",
+ " -571542809_01 | \n",
+ " 571542809_01 | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 18 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 19 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 20 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ " -571542809_01 | \n",
+ " 571542811_01 | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 21 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " 571542107_02 | \n",
+ " 571542809_01 | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 22 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " 571540304_02 | \n",
+ " 571556450_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 23 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " 571556450_02 | \n",
+ " 571540304_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 24 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ " 571556450_02 | \n",
+ " 571500475_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 25 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " 571540304_02 | \n",
+ " 571540303_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 26 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 000 | \n",
+ " 571540303_02.21 | \n",
+ " 571556450_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 27 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571540303_02.21 | \n",
+ " 571500475_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 28 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " -571500475_01 | \n",
+ " 571540303_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 29 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " -571500475_01 | \n",
+ " 571540304_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 30 | \n",
+ " 201 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " -571500569_01 | \n",
+ " 571500583_02 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 31 | \n",
+ " 201 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " -571500569_01 | \n",
+ " 571500618_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 32 | \n",
+ " 201 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 000 | \n",
+ " 571500618_02 | \n",
+ " 571500583_02 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 33 | \n",
+ " 201 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571500618_02 | \n",
+ " 571500617_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 34 | \n",
+ " 201 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " 571500617_02 | \n",
+ " 571500618_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 35 | \n",
+ " 201 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571500618_02 | \n",
+ " 571500617_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 36 | \n",
+ " 201 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " 571500617_02 | \n",
+ " 571500618_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 37 | \n",
+ " 201 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " 571500617_02 | \n",
+ " 571500569_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 38 | \n",
+ " 201 | \n",
+ " 5 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ " 571500583_01 | \n",
+ " 571500617_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 39 | \n",
+ " 201 | \n",
+ " 5 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " 571500583_01 | \n",
+ " 571500569_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 40 | \n",
+ " 202 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " 571510152_02 | \n",
+ " -571510152_01 | \n",
+ " i9 | \n",
+ "
\n",
+ " \n",
+ " 41 | \n",
+ " 202 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571510152_01 | \n",
+ " 571510152_01.65 | \n",
+ " i9 | \n",
+ "
\n",
+ " \n",
+ " 42 | \n",
+ " 202 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i9 | \n",
+ "
\n",
+ " \n",
+ " 43 | \n",
+ " 202 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i9 | \n",
+ "
\n",
+ " \n",
+ " 44 | \n",
+ " 206 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " -571511538_02 | \n",
+ " 571542073_02 | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 45 | \n",
+ " 206 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " 571542073_01 | \n",
+ " 571511538_02 | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 46 | \n",
+ " 206 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 47 | \n",
+ " 206 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 48 | \n",
+ " 206 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " -571511538_02 | \n",
+ " 571542073_02 | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 49 | \n",
+ " 206 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " 571542073_01 | \n",
+ " 571511538_02 | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 50 | \n",
+ " 206 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 51 | \n",
+ " 206 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 52 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " -571542115_01 | \n",
+ " 571500535_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 53 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 54 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ " 571500535_02.18 | \n",
+ " 571511538_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 55 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571500535_02.18 | \n",
+ " 571542115_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 56 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 359 | \n",
+ " 090 | \n",
+ " 571511538_02.121 | \n",
+ " 571542115_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 57 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " 571511538_02.121 | \n",
+ " 571500585_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 58 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " 571500585_02 | \n",
+ " 571511538_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 59 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " 571500585_02 | \n",
+ " 571500535_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 175 1 A 8 남 북 179 004 \n",
+ "1 175 1 B 4 북 남 003 176 \n",
+ "2 175 2 A 7 북 동 001 095 \n",
+ "3 175 2 B 3 남 서 179 270 \n",
+ "4 175 3 A 6 동 서 090 270 \n",
+ "5 175 3 B 1 동 남 090 180 \n",
+ "6 175 4 A 5 서 북 268 000 \n",
+ "7 175 4 B 2 서 동 270 090 \n",
+ "8 176 1 A 8 남 북 180 000 \n",
+ "9 176 1 B 4 북 남 359 180 \n",
+ "10 176 2 A 8 남 북 180 000 \n",
+ "11 176 2 B 3 남 서 180 270 \n",
+ "12 176 3 A 5 서 북 270 356 \n",
+ "13 176 3 B 18 NaN NaN NaN NaN \n",
+ "14 177 1 A 8 남 북 180 000 \n",
+ "15 177 1 B 4 북 남 001 176 \n",
+ "16 177 2 A 7 북 동 000 090 \n",
+ "17 177 2 B 3 남 서 179 270 \n",
+ "18 177 3 A 17 NaN NaN NaN NaN \n",
+ "19 177 3 B 18 NaN NaN NaN NaN \n",
+ "20 177 4 A 5 서 북 268 000 \n",
+ "21 177 4 B 1 동 남 090 180 \n",
+ "22 178 1 A 8 남 북 180 000 \n",
+ "23 178 1 B 4 북 남 000 180 \n",
+ "24 178 2 A 7 북 동 000 090 \n",
+ "25 178 2 B 3 남 서 180 270 \n",
+ "26 178 3 A 5 서 북 270 000 \n",
+ "27 178 3 B 2 서 동 270 090 \n",
+ "28 178 4 A 6 동 서 090 270 \n",
+ "29 178 4 B 1 동 남 090 180 \n",
+ "30 201 1 A 8 남 북 180 000 \n",
+ "31 201 1 B 3 남 서 180 270 \n",
+ "32 201 2 A 5 서 북 270 000 \n",
+ "33 201 2 B 2 서 동 270 090 \n",
+ "34 201 3 A 6 동 서 090 270 \n",
+ "35 201 3 B 2 서 동 270 090 \n",
+ "36 201 4 A 6 동 서 090 270 \n",
+ "37 201 4 B 1 동 남 090 180 \n",
+ "38 201 5 A 7 북 동 000 090 \n",
+ "39 201 5 B 4 북 남 000 180 \n",
+ "40 202 1 A 6 동 서 090 270 \n",
+ "41 202 1 B 2 서 동 270 090 \n",
+ "42 202 2 A 17 NaN NaN NaN NaN \n",
+ "43 202 2 B 18 NaN NaN NaN NaN \n",
+ "44 206 1 A 8 남 북 180 000 \n",
+ "45 206 1 B 4 북 남 000 180 \n",
+ "46 206 2 A 17 NaN NaN NaN NaN \n",
+ "47 206 2 B 18 NaN NaN NaN NaN \n",
+ "48 206 3 A 8 남 북 180 000 \n",
+ "49 206 3 B 4 북 남 000 180 \n",
+ "50 206 4 A 17 NaN NaN NaN NaN \n",
+ "51 206 4 B 18 NaN NaN NaN NaN \n",
+ "52 210 1 A 6 동 서 090 270 \n",
+ "53 210 1 B 18 NaN NaN NaN NaN \n",
+ "54 210 2 A 5 서 북 268 000 \n",
+ "55 210 2 B 2 서 동 270 090 \n",
+ "56 210 3 A 7 북 동 359 090 \n",
+ "57 210 3 B 4 북 남 000 180 \n",
+ "58 210 4 A 8 남 북 180 000 \n",
+ "59 210 4 B 3 남 서 180 270 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 -571542797_02 571500487_01 i0 \n",
+ "1 -571500487_01 571542797_02 i0 \n",
+ "2 -571500487_01 571545870_01 i0 \n",
+ "3 -571542797_02 571510153_01 i0 \n",
+ "4 571545870_02 571510153_01 i0 \n",
+ "5 571545870_02 571542797_02 i0 \n",
+ "6 571510153_02 571500487_01 i0 \n",
+ "7 571510153_02 571545870_01 i0 \n",
+ "8 -571542810_01 -571542797_02.99 i1 \n",
+ "9 571542797_02.99 571542810_01 i1 \n",
+ "10 -571542810_01 -571542797_02.99 i1 \n",
+ "11 -571542810_01 571543469_01 i1 \n",
+ "12 571543469_02 -571542797_02.99 i1 \n",
+ "13 NaN NaN i1 \n",
+ "14 -571542809_01 571542811_01 i2 \n",
+ "15 571542811_02 571542809_01 i2 \n",
+ "16 571542811_02 571542107_01 i2 \n",
+ "17 -571542809_01 571542809_01 i2 \n",
+ "18 NaN NaN i2 \n",
+ "19 NaN NaN i2 \n",
+ "20 -571542809_01 571542811_01 i2 \n",
+ "21 571542107_02 571542809_01 i2 \n",
+ "22 571540304_02 571556450_01 i3 \n",
+ "23 571556450_02 571540304_01 i3 \n",
+ "24 571556450_02 571500475_01 i3 \n",
+ "25 571540304_02 571540303_01 i3 \n",
+ "26 571540303_02.21 571556450_01 i3 \n",
+ "27 571540303_02.21 571500475_01 i3 \n",
+ "28 -571500475_01 571540303_01 i3 \n",
+ "29 -571500475_01 571540304_01 i3 \n",
+ "30 -571500569_01 571500583_02 i8 \n",
+ "31 -571500569_01 571500618_01 i8 \n",
+ "32 571500618_02 571500583_02 i8 \n",
+ "33 571500618_02 571500617_01 i8 \n",
+ "34 571500617_02 571500618_01 i8 \n",
+ "35 571500618_02 571500617_01 i8 \n",
+ "36 571500617_02 571500618_01 i8 \n",
+ "37 571500617_02 571500569_01 i8 \n",
+ "38 571500583_01 571500617_01 i8 \n",
+ "39 571500583_01 571500569_01 i8 \n",
+ "40 571510152_02 -571510152_01 i9 \n",
+ "41 571510152_01 571510152_01.65 i9 \n",
+ "42 NaN NaN i9 \n",
+ "43 NaN NaN i9 \n",
+ "44 -571511538_02 571542073_02 i7 \n",
+ "45 571542073_01 571511538_02 i7 \n",
+ "46 NaN NaN i7 \n",
+ "47 NaN NaN i7 \n",
+ "48 -571511538_02 571542073_02 i7 \n",
+ "49 571542073_01 571511538_02 i7 \n",
+ "50 NaN NaN i7 \n",
+ "51 NaN NaN i7 \n",
+ "52 -571542115_01 571500535_01 i6 \n",
+ "53 NaN NaN i6 \n",
+ "54 571500535_02.18 571511538_01 i6 \n",
+ "55 571500535_02.18 571542115_01 i6 \n",
+ "56 571511538_02.121 571542115_01 i6 \n",
+ "57 571511538_02.121 571500585_01 i6 \n",
+ "58 571500585_02 571511538_01 i6 \n",
+ "59 571500585_02 571500535_01 i6 "
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# [네트워크], [교차로-노드 매칭], [교차로정보] 불러오기\n",
+ "net = sumolib.net.readNet('../../Data/networks/SN_sample.net.xml')\n",
+ "inter_node = pd.read_csv('../../Data/tables/inter_node.csv', index_col=0)\n",
+ "inter_info = pd.read_csv('../../Data/tables/inter_info.csv', index_col=0)\n",
+ "\n",
+ "inter_node1 = inter_node[inter_node.inter_type == 'parent'].drop('inter_type', axis=1)\n",
+ "inter_info1 = inter_info[['inter_no', 'inter_lat', 'inter_lon']]\n",
+ "inter = pd.merge(inter_node1, inter_info1, how='left', left_on=['inter_no'],\n",
+ " right_on=['inter_no']).drop_duplicates()\n",
+ "\n",
+ "inter2node = dict(zip(inter['inter_no'], inter['node_id']))\n",
+ "\n",
+ "match5 = match4.copy()\n",
+ "# 진입진출ID 매칭\n",
+ "for index, row in match5.iterrows():\n",
+ " node_id = inter2node[row.inter_no]\n",
+ " node = net.getNode(node_id)\n",
+ " # 교차로의 모든 (from / to) edges\n",
+ " inc_edges = [edge for edge in node.getIncoming() if edge.getFunction() == ''] # incoming edges\n",
+ " out_edges = [edge for edge in node.getOutgoing() if edge.getFunction() == ''] # outgoing edges\n",
+ " # 교차로의 모든 (from / to) directions\n",
+ " inc_dirs = []\n",
+ " for inc_edge in inc_edges:\n",
+ " start = inc_edge.getShape()[-2]\n",
+ " end = inc_edge.getShape()[-1]\n",
+ " inc_dir = np.array(end) - np.array(start)\n",
+ " inc_dir = inc_dir / (inc_dir ** 2).sum() ** 0.5\n",
+ " inc_dirs.append(inc_dir)\n",
+ " out_dirs = []\n",
+ " for out_edge in out_edges:\n",
+ " start = out_edge.getShape()[0]\n",
+ " end = out_edge.getShape()[1]\n",
+ " out_dir = np.array(end) - np.array(start)\n",
+ " out_dir = out_dir / (out_dir ** 2).sum() ** 0.5\n",
+ " out_dirs.append(out_dir)\n",
+ " # 진입각, 진출각 불러오기\n",
+ " if not pd.isna(row.inc_angle):\n",
+ " inc_angle = int(row.inc_angle)\n",
+ " out_angle = int(row.out_angle)\n",
+ " # 방위각을 일반각으로 가공, 라디안 변환, 단위벡터로 변환\n",
+ " inc_angle = (-90 - inc_angle) % 360\n",
+ " inc_angle = inc_angle * np.pi / 180.\n",
+ " inc_dir_true = np.array([np.cos(inc_angle), np.sin(inc_angle)])\n",
+ " out_angle = (90 - out_angle) % 360\n",
+ " out_angle = out_angle * np.pi / 180.\n",
+ " out_dir_true = np.array([np.cos(out_angle), np.sin(out_angle)])\n",
+ " # 매칭 엣지 반환\n",
+ " inc_index = np.array([np.dot(inc_dir, inc_dir_true) for inc_dir in inc_dirs]).argmax()\n",
+ " out_index = np.array([np.dot(out_dir, out_dir_true) for out_dir in out_dirs]).argmax()\n",
+ " inc_edge_id = inc_edges[inc_index].getID()\n",
+ " out_edge_id = out_edges[out_index].getID()\n",
+ " match5.at[index, 'inc_edge'] = inc_edge_id\n",
+ " match5.at[index, 'out_edge'] = out_edge_id\n",
+ "match5['node_id'] = match5['inter_no'].map(inter2node)\n",
+ "match5 = match5.sort_values(by=['inter_no','phase_no','ring_type']).reset_index(drop=True)\n",
+ "match5"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array(['u00', 'u20', 'u30', 'u31', 'u32', 'u60'], dtype=object)"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# 유턴/연동교차로에 대하여 진입ID, 진출ID 부여\n",
+ "node2inter = dict(zip(inter_node['node_id'], inter_node['inter_no']))\n",
+ "\n",
+ "uturn = pd.read_csv('../../Data/tables/child_uturn.csv')\n",
+ "coord = pd.read_csv('../../Data/tables/child_coord.csv')\n",
+ "\n",
+ "child_ids = inter_node[inter_node.inter_type=='child'].node_id.unique()\n",
+ "ch2pa = {} # child to parent\n",
+ "for child_id in child_ids:\n",
+ " parent_no = inter_node[inter_node.node_id==child_id].inter_no.iloc[0]\n",
+ " sub_inter_node = inter_node[inter_node.inter_no==parent_no]\n",
+ " ch2pa[child_id] = sub_inter_node[sub_inter_node.inter_type=='parent'].iloc[0].node_id\n",
+ "directions = ['북', '북동', '동', '남동', '남', '남서', '서', '북서'] # 정북기준 시계방향으로 8방향\n",
+ "u_ids = uturn.child_id.unique()\n",
+ "u_ids"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "u00 i0 좌회전시 북\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 179 | \n",
+ " 004 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 003 | \n",
+ " 176 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 19 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 001 | \n",
+ " 095 | \n",
+ " 571500487_02 | \n",
+ " 571500487_01.32 | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 179 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 175 1 A 8 남 북 179 004 \n",
+ "1 175 1 B 4 북 남 003 176 \n",
+ "2 175 2 A 19 북 동 001 095 \n",
+ "3 175 2 B 3 남 서 179 270 \n",
+ "4 175 3 A 6 동 서 090 270 \n",
+ "5 175 3 B 1 동 남 090 180 \n",
+ "6 175 4 A 5 서 북 268 000 \n",
+ "7 175 4 B 2 서 동 270 090 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 NaN NaN u00 \n",
+ "1 NaN NaN u00 \n",
+ "2 571500487_02 571500487_01.32 u00 \n",
+ "3 NaN NaN u00 \n",
+ "4 NaN NaN u00 \n",
+ "5 NaN NaN u00 \n",
+ "6 NaN NaN u00 \n",
+ "7 NaN NaN u00 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "u20 i2 보행신호시 북\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 001 | \n",
+ " 176 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 179 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 571542810_01.51 | \n",
+ " 571542810_02 | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 177 1 A 8 남 북 180 000 \n",
+ "1 177 1 B 4 북 남 001 176 \n",
+ "2 177 2 A 7 북 동 000 090 \n",
+ "3 177 2 B 3 남 서 179 270 \n",
+ "4 177 3 A 17 NaN NaN NaN NaN \n",
+ "5 177 3 B 18 NaN NaN NaN NaN \n",
+ "6 177 4 A 5 서 북 268 000 \n",
+ "7 177 4 B 1 동 남 090 180 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 NaN NaN u20 \n",
+ "1 NaN NaN u20 \n",
+ "2 NaN NaN u20 \n",
+ "3 NaN NaN u20 \n",
+ "4 571542810_01.51 571542810_02 u20 \n",
+ "5 NaN NaN u20 \n",
+ "6 NaN NaN u20 \n",
+ "7 NaN NaN u20 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "u30 i3 보행신호시 북\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 19 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " 571556452_01 | \n",
+ " 571556452_02 | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 178 1 A 8 남 북 180 000 \n",
+ "1 178 1 B 4 북 남 000 180 \n",
+ "2 178 2 A 7 북 동 000 090 \n",
+ "3 178 2 B 3 남 서 180 270 \n",
+ "4 178 3 A 5 서 북 270 000 \n",
+ "5 178 3 B 2 서 동 270 090 \n",
+ "6 178 4 A 19 동 서 090 270 \n",
+ "7 178 4 B 1 동 남 090 180 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 NaN NaN u30 \n",
+ "1 NaN NaN u30 \n",
+ "2 NaN NaN u30 \n",
+ "3 NaN NaN u30 \n",
+ "4 NaN NaN u30 \n",
+ "5 NaN NaN u30 \n",
+ "6 571556452_01 571556452_02 u30 \n",
+ "7 NaN NaN u30 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "u31 i3 보행신호시 동\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 19 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " 571500475_02 | \n",
+ " 571500475_01.26 | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 178 1 A 19 남 북 180 000 \n",
+ "1 178 1 B 4 북 남 000 180 \n",
+ "2 178 2 A 7 북 동 000 090 \n",
+ "3 178 2 B 3 남 서 180 270 \n",
+ "4 178 3 A 5 서 북 270 000 \n",
+ "5 178 3 B 2 서 동 270 090 \n",
+ "6 178 4 A 6 동 서 090 270 \n",
+ "7 178 4 B 1 동 남 090 180 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 571500475_02 571500475_01.26 u31 \n",
+ "1 NaN NaN u31 \n",
+ "2 NaN NaN u31 \n",
+ "3 NaN NaN u31 \n",
+ "4 NaN NaN u31 \n",
+ "5 NaN NaN u31 \n",
+ "6 NaN NaN u31 \n",
+ "7 NaN NaN u31 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "u32 i3 보행신호시 서\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 19 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " 571540303_02 | \n",
+ " -571540303_02 | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 178 1 A 8 남 북 180 000 \n",
+ "1 178 1 B 19 북 남 000 180 \n",
+ "2 178 2 A 7 북 동 000 090 \n",
+ "3 178 2 B 3 남 서 180 270 \n",
+ "4 178 3 A 5 서 북 270 000 \n",
+ "5 178 3 B 2 서 동 270 090 \n",
+ "6 178 4 A 6 동 서 090 270 \n",
+ "7 178 4 B 1 동 남 090 180 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 NaN NaN u32 \n",
+ "1 571540303_02 -571540303_02 u32 \n",
+ "2 NaN NaN u32 \n",
+ "3 NaN NaN u32 \n",
+ "4 NaN NaN u32 \n",
+ "5 NaN NaN u32 \n",
+ "6 NaN NaN u32 \n",
+ "7 NaN NaN u32 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "u60 i6 직좌시 서\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 19 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ " 571500535_02 | \n",
+ " -571500535_02 | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 19 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571500535_02 | \n",
+ " -571500535_02 | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 359 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 210 1 A 6 동 서 090 270 \n",
+ "1 210 1 B 18 NaN NaN NaN NaN \n",
+ "2 210 2 A 19 서 북 268 000 \n",
+ "3 210 2 B 19 서 동 270 090 \n",
+ "4 210 3 A 7 북 동 359 090 \n",
+ "5 210 3 B 4 북 남 000 180 \n",
+ "6 210 4 A 8 남 북 180 000 \n",
+ "7 210 4 B 3 남 서 180 270 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 NaN NaN u60 \n",
+ "1 NaN NaN u60 \n",
+ "2 571500535_02 -571500535_02 u60 \n",
+ "3 571500535_02 -571500535_02 u60 \n",
+ "4 NaN NaN u60 \n",
+ "5 NaN NaN u60 \n",
+ "6 NaN NaN u60 \n",
+ "7 NaN NaN u60 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 571542116_01 | \n",
+ " -571542116_02.96 | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 571542116_02.96 | \n",
+ " 571542116_02.164 | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 571542116_01 | \n",
+ " -571542116_02.96 | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 571542116_02.96 | \n",
+ " 571542116_02.164 | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 571542116_01 | \n",
+ " -571542116_02.96 | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 571542116_02.96 | \n",
+ " 571542116_02.164 | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle \\\n",
+ "0 178 1 A 20 NaN NaN NaN \n",
+ "1 178 1 B 20 NaN NaN NaN \n",
+ "2 178 2 A 20 NaN NaN NaN \n",
+ "3 178 2 B 20 NaN NaN NaN \n",
+ "4 178 3 A 20 NaN NaN NaN \n",
+ "5 178 3 B 20 NaN NaN NaN \n",
+ "6 178 4 A 20 NaN NaN NaN \n",
+ "7 178 4 B 20 NaN NaN NaN \n",
+ "\n",
+ " out_angle inc_edge out_edge node_id \n",
+ "0 NaN NaN NaN c30 \n",
+ "1 NaN NaN NaN c30 \n",
+ "2 NaN 571542116_01 -571542116_02.96 c30 \n",
+ "3 NaN 571542116_02.96 571542116_02.164 c30 \n",
+ "4 NaN 571542116_01 -571542116_02.96 c30 \n",
+ "5 NaN 571542116_02.96 571542116_02.164 c30 \n",
+ "6 NaN 571542116_01 -571542116_02.96 c30 \n",
+ "7 NaN 571542116_02.96 571542116_02.164 c30 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 179 | \n",
+ " 004 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 003 | \n",
+ " 176 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 001 | \n",
+ " 095 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 179 | \n",
+ " 270 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 19 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571500535_02 | \n",
+ " -571500535_02 | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 359 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
116 rows × 11 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 175 1 A 8 남 북 179 004 \n",
+ "1 175 1 B 4 북 남 003 176 \n",
+ "2 175 2 A 7 북 동 001 095 \n",
+ "3 175 2 B 3 남 서 179 270 \n",
+ "4 175 3 A 6 동 서 090 270 \n",
+ ".. ... ... ... ... ... ... ... ... \n",
+ "3 210 2 B 19 서 동 270 090 \n",
+ "4 210 3 A 7 북 동 359 090 \n",
+ "5 210 3 B 4 북 남 000 180 \n",
+ "6 210 4 A 8 남 북 180 000 \n",
+ "7 210 4 B 3 남 서 180 270 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 -571542797_02 571500487_01 i0 \n",
+ "1 -571500487_01 571542797_02 i0 \n",
+ "2 -571500487_01 571545870_01 i0 \n",
+ "3 -571542797_02 571510153_01 i0 \n",
+ "4 571545870_02 571510153_01 i0 \n",
+ ".. ... ... ... \n",
+ "3 571500535_02 -571500535_02 u60 \n",
+ "4 NaN NaN u60 \n",
+ "5 NaN NaN u60 \n",
+ "6 NaN NaN u60 \n",
+ "7 NaN NaN u60 \n",
+ "\n",
+ "[116 rows x 11 columns]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# 유턴/연동교차로에 대하여 진입ID, 진출ID 부여\n",
+ "node2inter = dict(zip(inter_node['node_id'], inter_node['inter_no']))\n",
+ "\n",
+ "uturn = pd.read_csv('../../Data/tables/child_uturn.csv')\n",
+ "coord = pd.read_csv('../../Data/tables/child_coord.csv')\n",
+ "child_ids = inter_node[inter_node.inter_type=='child'].node_id.unique()\n",
+ "ch2pa = {} # child to parent\n",
+ "for child_id in child_ids:\n",
+ " parent_no = inter_node[inter_node.node_id==child_id].inter_no.iloc[0]\n",
+ " sub_inter_node = inter_node[inter_node.inter_no==parent_no]\n",
+ " ch2pa[child_id] = sub_inter_node[sub_inter_node.inter_type=='parent'].iloc[0].node_id\n",
+ "directions = ['북', '북동', '동', '남동', '남', '남서', '서', '북서'] # 정북기준 시계방향으로 8방향\n",
+ "u_ids = uturn.child_id.unique()\n",
+ "# 각 child uturn node에 대하여 (inc_edge_id, out_edge_id) 부여\n",
+ "cmatches = []\n",
+ "for _, row in uturn.iterrows():\n",
+ " child_id = row.child_id\n",
+ " parent_id = row.parent_id\n",
+ " direction = row.direction\n",
+ " condition = row.condition\n",
+ " inc_edge_id = row.inc_edge\n",
+ " out_edge_id = row.out_edge\n",
+ " ind = directions.index(direction)\n",
+ " if condition == \"좌회전시\":\n",
+ " print(child_id, parent_id, condition, direction)\n",
+ " inc_dire = direction\n",
+ " out_dire_A = out_dire_B = directions[(ind + 2) % len(directions)]\n",
+ " elif condition == \"직진시\":\n",
+ " print(child_id, parent_id, condition, direction)\n",
+ " inc_dire = direction\n",
+ " out_dire_A = out_dire_B = directions[(ind + 4) % len(directions)]\n",
+ " elif condition == \"직좌시\":\n",
+ " print(child_id, parent_id, condition, direction)\n",
+ " inc_dire = direction\n",
+ " out_dire_A = directions[(ind + 2) % len(directions)]\n",
+ " out_dire_B = directions[(ind + 4) % len(directions)]\n",
+ " elif condition == \"보행신호시\":\n",
+ " print(child_id, parent_id, condition, direction)\n",
+ " inc_dire = directions[(ind + 2) % len(directions)]\n",
+ " out_dire_A = directions[(ind - 2) % len(directions)]\n",
+ " out_dire_B = directions[(ind - 2) % len(directions)]\n",
+ " cmatch = match5.copy()[match5.node_id==parent_id] # match dataframe for a child node\n",
+ " cmatch = cmatch.sort_values(by=['phase_no', 'ring_type']).reset_index(drop=True)\n",
+ " cmatch['node_id'] = child_id\n",
+ " cmatch[['inc_edge', 'out_edge']] = np.nan\n",
+ " if condition == '직좌시':\n",
+ " ap = cmatch[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A)].phase_no.iloc[0]\n",
+ " bp = cmatch[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B)].phase_no.iloc[0]\n",
+ " # 직진과 좌회전이 같은 현시에 있는 경우에만 (inc_edge_id, out_edge_id)를 부여한다.\n",
+ " if ap == bp:\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " elif condition == '보행신호시':\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " # 이동류번호가 17(보행신호)이면서 유턴노드방향으로 가는 신호가 없으면 (inc_edge_id, out_edge_id)를 부여한다.\n",
+ " cmatch.loc[(cmatch.move_no==17) & (cmatch.out_dir!=direction), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " else:\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " # 유턴신호의 이동류번호를 19로 부여한다.\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), 'move_no'] = 19\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), 'move_no'] = 19\n",
+ " display(cmatch)\n",
+ " cmatches.append(cmatch)\n",
+ "\n",
+ "# 각 child coordination node에 대하여 (inc_edge_id, out_edge_id) 부여\n",
+ "coord['inter_no'] = coord['parent_id'].map(node2inter)\n",
+ "coord = coord.rename(columns={'child_id':'node_id'})\n",
+ "coord[['inc_dir', 'out_dir', 'inc_angle','out_angle']] = np.nan\n",
+ "coord['move_no'] = 20\n",
+ "coord = coord[['inter_no', 'phase_no', 'ring_type', 'move_no', 'inc_dir', 'out_dir', 'inc_angle','out_angle', 'inc_edge', 'out_edge', 'node_id']]\n",
+ "# display(coord)\n",
+ "cmatches = pd.concat(cmatches)\n",
+ "display(coord)\n",
+ "match6 = pd.concat([match5, cmatches, coord]).drop_duplicates().sort_values(by=['inter_no', 'node_id', 'phase_no', 'ring_type'])\n",
+ "# with pd.option_context('display.max_rows', None, 'display.max_columns', None):\n",
+ "match6.to_csv('../../Data/tables/matching/match6.csv')\n",
+ "display(match6)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 69 | \n",
+ " 210 | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 571500585_02 | \n",
+ " 571511538_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 70 | \n",
+ " 210 | \n",
+ " 21 | \n",
+ " 북 | \n",
+ " 서 | \n",
+ " 571511538_02.121 | \n",
+ " 571500535_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 71 | \n",
+ " 210 | \n",
+ " 21 | \n",
+ " 서 | \n",
+ " 남 | \n",
+ " 571500535_02.18 | \n",
+ " 571500585_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 72 | \n",
+ " 210 | \n",
+ " 21 | \n",
+ " 남 | \n",
+ " 동 | \n",
+ " 571500585_02 | \n",
+ " 571542115_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 73 | \n",
+ " 210 | \n",
+ " 21 | \n",
+ " 동 | \n",
+ " 북 | \n",
+ " -571542115_01 | \n",
+ " 571511538_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
74 rows × 7 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no move_no inc_dir out_dir inc_edge out_edge node_id\n",
+ "0 175 1 동 남 571545870_02 571542797_02 i0\n",
+ "1 175 2 서 동 571510153_02 571545870_01 i0\n",
+ "2 175 3 남 서 -571542797_02 571510153_01 i0\n",
+ "3 175 4 북 남 -571500487_01 571542797_02 i0\n",
+ "4 175 5 서 북 571510153_02 571500487_01 i0\n",
+ ".. ... ... ... ... ... ... ...\n",
+ "69 210 8 남 북 571500585_02 571511538_01 i6\n",
+ "70 210 21 북 서 571511538_02.121 571500535_01 i6\n",
+ "71 210 21 서 남 571500535_02.18 571500585_01 i6\n",
+ "72 210 21 남 동 571500585_02 571542115_01 i6\n",
+ "73 210 21 동 북 -571542115_01 571511538_01 i6\n",
+ "\n",
+ "[74 rows x 7 columns]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# 이동류 매칭\n",
+ "# 각 교차로에 대하여, 가능한 모든 이동류(1~18, 21)에 대한 진입·진출엣지ID를 지정한다.\n",
+ "# 모든 이동류에 대해 지정하므로, 시차제시 이전과 다른 이동류가 등장하더라도 항상 진입·진출 엣지 ID를 지정할 수 있다.\n",
+ "match7 = match6.copy()\n",
+ "match7 = match7[['inter_no', 'move_no', 'inc_dir', 'out_dir', 'inc_edge', 'out_edge', 'node_id']]\n",
+ "\n",
+ "parent_ids = sorted(inter_node[inter_node.inter_type=='parent'].node_id.unique())\n",
+ "child_ids = sorted(inter_node[inter_node.inter_type=='child'].node_id.unique())\n",
+ "\n",
+ "# (1) 가능한 (진입방향, 진출방향) 목록\n",
+ "flows = nema.dropna().apply(lambda row: (row['inc_dir'], row['out_dir']), axis=1).tolist()\n",
+ "# (2) 각 교차로별 방향 목록 : pdires (possible directions)\n",
+ "pdires = {}\n",
+ "for node_id in parent_ids:\n",
+ " dires = match7[match7.node_id == node_id][['inc_dir','out_dir']].values.flatten()\n",
+ " dires = {dire for dire in dires if type(dire)==str}\n",
+ " pdires[node_id] = dires\n",
+ "# (3) 각 (교차로, 진입방향) 별 진입id 목록 : inc2id (incoming direction to incoming edge_id)\n",
+ "inc2id = {}\n",
+ "for node_id in parent_ids:\n",
+ " for inc_dir in pdires[node_id]:\n",
+ " df = match7[(match7.node_id==node_id) & (match7.inc_dir==inc_dir)]\n",
+ " inc2id[(node_id, inc_dir)] = df.inc_edge.iloc[0]\n",
+ "# (4) 각 (교차로, 진출방향) 별 진출id 목록 : out2id (outgoing direction to outgoing edge_id)\n",
+ "out2id = {}\n",
+ "for node_id in parent_ids:\n",
+ " for out_dir in pdires[node_id]:\n",
+ " df = match7[(match7.node_id==node_id) & (match7.out_dir==out_dir)]\n",
+ " out2id[(node_id, out_dir)] = df.out_edge.iloc[0]\n",
+ "# (5) 각 교차로별 가능한 (진입방향, 진출방향) 목록 : pflow (possible flows)\n",
+ "pflow = {}\n",
+ "for node_id in parent_ids:\n",
+ " pflow[node_id] = [flow for flow in flows if set(flow).issubset(pdires[node_id])]\n",
+ "# (6) 가능한 이동류에 대하여 진입id, 진출id 배정 : matching\n",
+ "node2inter = dict(zip(match7['node_id'], match7['inter_no']))\n",
+ "dires_right = ['북', '서', '남', '동', '북'] # ex (북, 서), (서, 남) 등은 우회전 flow\n",
+ "matching = []\n",
+ "for node_id in parent_ids:\n",
+ " inter_no = node2inter[node_id]\n",
+ " # 좌회전과 직진(1 ~ 16)\n",
+ " for (inc_dir, out_dir) in pflow[node_id]:\n",
+ " move_no = nema[(nema.inc_dir==inc_dir) & (nema.out_dir==out_dir)].move_no.iloc[0]\n",
+ " inc_edge = inc2id[(node_id, inc_dir)]\n",
+ " out_edge = out2id[(node_id, out_dir)]\n",
+ " new_row = pd.DataFrame({'inter_no':[inter_no], 'move_no':[move_no],\n",
+ " 'inc_dir':[inc_dir], 'out_dir':[out_dir],\n",
+ " 'inc_edge':[inc_edge], 'out_edge':[out_edge], 'node_id':[node_id]})\n",
+ " matching.append(new_row)\n",
+ " # 보행신호(17), 전적색(18)\n",
+ " new_row = pd.DataFrame({'inter_no':[inter_no] * 2, 'move_no':[17, 18],\n",
+ " 'inc_dir':[None]*2, 'out_dir':[None]*2,\n",
+ " 'inc_edge':[None]*2, 'out_edge':[None]*2, 'node_id':[node_id]*2})\n",
+ " matching.append(new_row)\n",
+ " # 신호우회전(21)\n",
+ " for d in range(len(dires_right)-1):\n",
+ " inc_dir = dires_right[d]\n",
+ " out_dir = dires_right[d+1]\n",
+ " if {inc_dir, out_dir}.issubset(pdires[node_id]):\n",
+ " inc_edge = inc2id[(node_id, inc_dir)]\n",
+ " out_edge = out2id[(node_id, out_dir)]\n",
+ " new_row = pd.DataFrame({'inter_no':[inter_no], 'move_no':[21],\n",
+ " 'inc_dir':[inc_dir], 'out_dir':[out_dir],\n",
+ " 'inc_edge':[inc_edge], 'out_edge':[out_edge], 'node_id':[node_id]})\n",
+ " matching.append(new_row)\n",
+ "matching.append(match7[match7.node_id.isin(child_ids)])\n",
+ "matching = pd.concat(matching)\n",
+ "matching = matching.dropna().sort_values(by=['inter_no', 'node_id', 'move_no']).reset_index(drop=True)\n",
+ "matching['move_no'] = matching['move_no'].astype(int)\n",
+ "matching.to_csv('../../Data/tables/matching/matching.csv')\n",
+ "display(matching)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# B. 5초 간격으로 이동류번호 수집"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " 0%| | 0/17280 [00:00, ?it/s]"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "100%|██████████| 17280/17280 [02:07<00:00, 135.82it/s]\n"
+ ]
+ }
+ ],
+ "source": [
+ "# 5초 단위로 이동류번호 저장 및 신호이력에서 유닉스시각 가져와서 표시, 한시간동안의 데이터만 보관\n",
+ "midnight = int(datetime(2024, 1, 5, 0, 0, 0).timestamp())\n",
+ "next_day = int(datetime(2024, 1, 6, 0, 0, 0).timestamp())\n",
+ "fsecs = range(midnight, next_day, 5) # fsecs : unix time by Five SECondS\n",
+ "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
+ "# time2move = dict(zip(fsecs,moves)) # move : 어느 순간의 이동류정보\n",
+ "history = pd.read_csv('../../Data/tables/history.csv', index_col=0)\n",
+ "\n",
+ "time2movement = {} # movement : 어느 순간의, 그 순간으로부터 한시간 동안의 (교차로번호 + 현시별이동류번호 + 시작시간)\n",
+ "# - 아래 절차를 5초마다 반복\n",
+ "for fsec in tqdm(fsecs): # fsec : unix time by Five SECond\n",
+ " # 1. 상태 테이블 조회해서 전체 데이터중 필요데이터(교차로번호, A링 현시번호, A링 이동류번호, B링 현시번호, B링 이동류번호)만 수집 : A\n",
+ " # move = time2move[fsec]\n",
+ " move = pd.read_csv(f'../../Data/tables/moves/move_{fsec}.csv', index_col=0)\n",
+ " # 2. 이력 테이블 조회해서 교차로별로 유닉스시간 최대인 데이터(교차로변호, 종료유닉스타임)만 수집 : B\n",
+ " recent_histories = [group.iloc[-1:] for _, group in history[history['end_unix'] < fsec].groupby('inter_no')] # 교차로별로 유닉스시간이 최대인 행들\n",
+ " if not recent_histories:\n",
+ " rhistory = pd.DataFrame({'inter_no':[], 'end_unix':[]}) # recent history\n",
+ " else:\n",
+ " rhistory = pd.concat(recent_histories)\n",
+ " recent_unix = rhistory[['inter_no', 'end_unix']]\n",
+ " # 3. 상태 테이블 조회정보(A)와 이력 테이블 조회정보(B) 조인(키값 : 교차로번호) : C\n",
+ " move = pd.merge(move, recent_unix, how='left', on='inter_no')\n",
+ " move['end_unix'] = move['end_unix'].fillna(0).astype(int)\n",
+ " move = move.drop_duplicates()\n",
+ " # 4. C데이터 프레임에 신규 컬럼(시작 유닉스타임) 생성 후 종료유닉스 타임 값 입력, 종료 유닉스 타임 컬럼 제거\n",
+ " move = move.rename(columns = {'end_unix':'start_unix'})\n",
+ " # 5. 이동류 이력정보 READ\n",
+ " # - CSV 파일로 서버에 저장된 이동류정보를 읽어옴(파일이 없는 경우에는 데이터가 없는 프레임 D 생성)\n",
+ " try:\n",
+ " if isinstance(movement, pd.DataFrame): # movement가 존재할 경우 그걸 그대로 씀.\n",
+ " pass\n",
+ " else: \n",
+ " movement = pd.DataFrame()\n",
+ " except NameError: # movement가 존재하지 않는 경우 생성\n",
+ " movement = pd.DataFrame()\n",
+ " # 6. 이동류 이력정보 데이터테이블(D)에 C데이터 add\n",
+ " movement = pd.concat([movement, move])\n",
+ " # 7. D데이터 프레임에서 중복데이터 제거(교차로번호, 시작 유닉스타임, A링 현시번호, B링 현시번호 같은 행은 제거)\n",
+ " movement = movement.drop_duplicates(['inter_no','phas_A','phas_B','start_unix'])\n",
+ " # 8. D데이터 보관 시간 기준시간을 시작 유닉스 타임의 최대값 - 3600을 값으로 산출하고, 보관 시간 기준시간보다 작은 시작 유닉스 타임을 가진 행은 모두 제거(1시간 데이터만 보관)\n",
+ " movement = movement[movement.start_unix > fsec - 3600]\n",
+ " movement = movement.sort_values(by=['start_unix','inter_no','phas_A','phas_B']).reset_index(drop=True)\n",
+ "\n",
+ " time2movement[fsec] = movement\n",
+ " movement.to_csv(f'../../Data/tables/movements/movements_{fsec}.csv')\n",
+ "\n",
+ "# 각 movement들의 길이 시각화\n",
+ "import matplotlib.pyplot as plt\n",
+ "plt.plot(fsecs, [len(time2movement[fsec]) for fsec in fsecs])\n",
+ "plt.close()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# C. 5분 간격으로 신호이력 수집 및 통합테이블 생성"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plan = pd.read_csv('../../Data/tables/plan.csv', index_col=0)\n",
+ "history = pd.read_csv('../../Data/tables/history.csv', index_col=0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " start_hour | \n",
+ " start_minute | \n",
+ " start_seconds | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1704380400 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 7 | \n",
+ " 0 | \n",
+ " 1704405600 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 9 | \n",
+ " 0 | \n",
+ " 1704412800 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 18 | \n",
+ " 30 | \n",
+ " 1704447000 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " start_hour start_minute start_seconds\n",
+ "0 0 0 1704380400\n",
+ "1 7 0 1704405600\n",
+ "2 9 0 1704412800\n",
+ "3 18 30 1704447000"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# split, isplit : A,B 분리 혹은 통합시 사용될 수 있는 딕셔너리\n",
+ "splits = {} # splits maps (inter_no, start_hour, start_minute) to split\n",
+ "for i, row in plan.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_hour = row.start_hour\n",
+ " start_minute = row.start_minute\n",
+ " cycle = row.cycle\n",
+ " cums_A = row[[f'dura_A{j}' for j in range(1,9)]].cumsum()\n",
+ " cums_B = row[[f'dura_B{j}' for j in range(1,9)]].cumsum()\n",
+ " splits[(inter_no, start_hour, start_minute)] = {} # split maps (phas_A, phas_B) to k\n",
+ " k = 0\n",
+ " for t in range(cycle):\n",
+ " new_phas_A = len(cums_A[cums_A < t]) + 1\n",
+ " new_phas_B = len(cums_B[cums_B < t]) + 1\n",
+ " if k == 0 or ((new_phas_A, new_phas_B) != (phas_A, phas_B)):\n",
+ " k += 1\n",
+ " phas_A = new_phas_A\n",
+ " phas_B = new_phas_B\n",
+ " splits[(inter_no, start_hour, start_minute)][(phas_A, phas_B)] = k\n",
+ "\n",
+ "isplits = {} # the inverse of splits\n",
+ "for i in splits:\n",
+ " isplits[i] = {splits[i][k]:k for k in splits[i]} # isplit maps k to (phas_A, phas_B)\n",
+ "\n",
+ "# timetable\n",
+ "timetable = plan[['start_hour', 'start_minute']].drop_duplicates()\n",
+ "timetable['start_seconds'] = midnight + timetable['start_hour'] * 3600 + timetable['start_minute'] * 60\n",
+ "timetable"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2024-01-05 03:20:00\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " start_unix | \n",
+ " dura_A1 | \n",
+ " dura_A2 | \n",
+ " dura_A3 | \n",
+ " dura_A4 | \n",
+ " dura_A5 | \n",
+ " dura_A6 | \n",
+ " dura_A7 | \n",
+ " dura_A8 | \n",
+ " dura_B1 | \n",
+ " dura_B2 | \n",
+ " dura_B3 | \n",
+ " dura_B4 | \n",
+ " dura_B5 | \n",
+ " dura_B6 | \n",
+ " dura_B7 | \n",
+ " dura_B8 | \n",
+ " cycle | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 60 | \n",
+ " 178 | \n",
+ " 1704388800 | \n",
+ " 38 | \n",
+ " 39 | \n",
+ " 40 | \n",
+ " 23 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 38 | \n",
+ " 39 | \n",
+ " 40 | \n",
+ " 23 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ "
\n",
+ " \n",
+ " 60 | \n",
+ " 201 | \n",
+ " 1704388800 | \n",
+ " 24 | \n",
+ " 24 | \n",
+ " 17 | \n",
+ " 58 | \n",
+ " 17 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 24 | \n",
+ " 24 | \n",
+ " 17 | \n",
+ " 58 | \n",
+ " 17 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ "
\n",
+ " \n",
+ " 60 | \n",
+ " 202 | \n",
+ " 1704388800 | \n",
+ " 39 | \n",
+ " 101 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 39 | \n",
+ " 101 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ "
\n",
+ " \n",
+ " 70 | \n",
+ " 206 | \n",
+ " 1704388800 | \n",
+ " 33 | \n",
+ " 35 | \n",
+ " 26 | \n",
+ " 26 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 33 | \n",
+ " 35 | \n",
+ " 26 | \n",
+ " 26 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 120 | \n",
+ "
\n",
+ " \n",
+ " 56 | \n",
+ " 177 | \n",
+ " 1704388801 | \n",
+ " 36 | \n",
+ " 20 | \n",
+ " 68 | \n",
+ " 26 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 36 | \n",
+ " 20 | \n",
+ " 68 | \n",
+ " 26 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 150 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 78 | \n",
+ " 210 | \n",
+ " 1704392159 | \n",
+ " 43 | \n",
+ " 29 | \n",
+ " 56 | \n",
+ " 22 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 24 | \n",
+ " 48 | \n",
+ " 56 | \n",
+ " 22 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 150 | \n",
+ "
\n",
+ " \n",
+ " 84 | \n",
+ " 178 | \n",
+ " 1704392160 | \n",
+ " 38 | \n",
+ " 39 | \n",
+ " 40 | \n",
+ " 23 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 38 | \n",
+ " 39 | \n",
+ " 40 | \n",
+ " 23 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ "
\n",
+ " \n",
+ " 84 | \n",
+ " 201 | \n",
+ " 1704392160 | \n",
+ " 24 | \n",
+ " 24 | \n",
+ " 17 | \n",
+ " 58 | \n",
+ " 17 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 24 | \n",
+ " 24 | \n",
+ " 17 | \n",
+ " 58 | \n",
+ " 17 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ "
\n",
+ " \n",
+ " 98 | \n",
+ " 206 | \n",
+ " 1704392160 | \n",
+ " 33 | \n",
+ " 35 | \n",
+ " 26 | \n",
+ " 26 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 33 | \n",
+ " 35 | \n",
+ " 26 | \n",
+ " 26 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 120 | \n",
+ "
\n",
+ " \n",
+ " 84 | \n",
+ " 202 | \n",
+ " 1704392211 | \n",
+ " 39 | \n",
+ " 101 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 39 | \n",
+ " 101 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
194 rows × 19 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no start_unix dura_A1 dura_A2 dura_A3 dura_A4 dura_A5 \\\n",
+ "60 178 1704388800 38 39 40 23 0 \n",
+ "60 201 1704388800 24 24 17 58 17 \n",
+ "60 202 1704388800 39 101 0 0 0 \n",
+ "70 206 1704388800 33 35 26 26 0 \n",
+ "56 177 1704388801 36 20 68 26 0 \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "78 210 1704392159 43 29 56 22 0 \n",
+ "84 178 1704392160 38 39 40 23 0 \n",
+ "84 201 1704392160 24 24 17 58 17 \n",
+ "98 206 1704392160 33 35 26 26 0 \n",
+ "84 202 1704392211 39 101 0 0 0 \n",
+ "\n",
+ " dura_A6 dura_A7 dura_A8 dura_B1 dura_B2 dura_B3 dura_B4 dura_B5 \\\n",
+ "60 0 0 0 38 39 40 23 0 \n",
+ "60 0 0 0 24 24 17 58 17 \n",
+ "60 0 0 0 39 101 0 0 0 \n",
+ "70 0 0 0 33 35 26 26 0 \n",
+ "56 0 0 0 36 20 68 26 0 \n",
+ ".. ... ... ... ... ... ... ... ... \n",
+ "78 0 0 0 24 48 56 22 0 \n",
+ "84 0 0 0 38 39 40 23 0 \n",
+ "84 0 0 0 24 24 17 58 17 \n",
+ "98 0 0 0 33 35 26 26 0 \n",
+ "84 0 0 0 39 101 0 0 0 \n",
+ "\n",
+ " dura_B6 dura_B7 dura_B8 cycle \n",
+ "60 0 0 0 140 \n",
+ "60 0 0 0 140 \n",
+ "60 0 0 0 140 \n",
+ "70 0 0 0 120 \n",
+ "56 0 0 0 150 \n",
+ ".. ... ... ... ... \n",
+ "78 0 0 0 150 \n",
+ "84 0 0 0 140 \n",
+ "84 0 0 0 140 \n",
+ "98 0 0 0 120 \n",
+ "84 0 0 0 140 \n",
+ "\n",
+ "[194 rows x 19 columns]"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "m = 40\n",
+ "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
+ "present_time = fmins[m] # 현재시점\n",
+ "print(datetime.fromtimestamp(present_time))\n",
+ "\n",
+ "# 1. 조회시점의 유닉스 타임 이전의 신호이력 수집\n",
+ "rhistory = history.copy() # recent history\n",
+ "rhistory = rhistory[(rhistory.end_unix < present_time)]\n",
+ "# 2. 시작 유닉스 타임컬럼 생성 후 종류 유닉스 타임에서 현시별 현시기간 컬럼의 합을 뺀 값으로 입력\n",
+ "# - 현시시간의 합을 뺀 시간의 +- 10초 이내에 이전 주기정보가 존재하면 그 유닉스 시간을 시작 유닉스시간 값으로 하고, 존재하지 않으면 현시시간의 합을 뺀 유닉스 시간을 시작 유닉스 시간으로 지정\n",
+ "for i, row in rhistory.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " end_unix = row.end_unix\n",
+ " elapsed_time = row[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]].sum() // 2 # 현시시간 합\n",
+ " # 이전 유닉스 존재하지 않음 : 현시시간 합의 차\n",
+ " start_unix = end_unix - elapsed_time\n",
+ " pre_rows = history[:i] # previous rows\n",
+ " if inter_no in pre_rows.inter_no.unique(): # 이전 유닉스 존재\n",
+ " pre_unix = pre_rows[pre_rows.inter_no == inter_no]['end_unix'].iloc[-1] # previous unix time\n",
+ " # 이전 유닉스 존재, abs < 10 : 이전 유닉스\n",
+ " if abs(pre_unix - start_unix) < 10:\n",
+ " start_unix = pre_unix\n",
+ " # 이전 유닉스 존재, abs >=10 : 현시시간 합의 차\n",
+ " else:\n",
+ " pass\n",
+ " rhistory.loc[i, 'start_unix'] = start_unix \n",
+ "rhistory[rhistory.isna()] = 0\n",
+ "rhistory['start_unix'] = rhistory['start_unix'].astype(int)\n",
+ "rhistory[['inter_no', 'start_unix', 'cycle']][rhistory.inter_no==175]\n",
+ "rhistory = rhistory[['inter_no', 'start_unix'] + [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)] + ['cycle']]\n",
+ "rhistory\n",
+ "\n",
+ "# 2-1. 참값 판단 프로세스\n",
+ "hours = np.array(range(midnight, next_day + 1, 3600)) # 정각에 해당하는 시각들 목록\n",
+ "\n",
+ "def calculate_DS(rhist, curr_unix):\n",
+ " ghour_lt_curr_unix = hours[hours <= curr_unix].max() # the greatest hour less than (or equal to) curr_unix\n",
+ " start_unixes = rhist.start_unix.unique()\n",
+ " start_unixes_lt_ghour = np.sort(start_unixes[start_unixes < ghour_lt_curr_unix]) # start unixes less than ghour_lt_curr_unix\n",
+ " # 기준유닉스(base_unix) : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 start_unix\n",
+ " if list(start_unixes_lt_ghour):\n",
+ " base_unix = start_unixes_lt_ghour[-5]\n",
+ " # start_unixes_lt_ghour가 비었을 경우에는 맨 앞 start_unix로 base_unix를 지정\n",
+ " else:\n",
+ " base_unix = rhist.start_unix.min()\n",
+ " D_n = curr_unix - base_unix\n",
+ " S_n_durs = rhist[(rhist.start_unix > base_unix) & (rhist.start_unix <= curr_unix)] \\\n",
+ " [[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " S_n = S_n_durs.values.sum() // 2\n",
+ " return D_n, S_n\n",
+ "\n",
+ "rhists = []\n",
+ "for inter_no in sorted(rhistory.inter_no.unique()):\n",
+ " rhist = rhistory.copy()[rhistory.inter_no==inter_no]\n",
+ " rhist = rhist.drop_duplicates(subset=['start_unix']).reset_index(drop=True)\n",
+ "\n",
+ " # D_n 및 S_n 값 정의\n",
+ " rhist['D_n'] = 0 # D_n : 시간차이\n",
+ " rhist['S_n'] = 0 # S_n : 현시시간합\n",
+ " for n in range(len(rhist)):\n",
+ " curr_unix = rhist.iloc[n].start_unix # current start_unix\n",
+ " rhist.loc[n, ['D_n', 'S_n']] = calculate_DS(rhist, curr_unix)\n",
+ "\n",
+ " # 이전시각, 현재시각\n",
+ " prev_unix = rhist.loc[0, 'start_unix'] # previous start_unix\n",
+ " curr_unix = rhist.loc[1, 'start_unix'] # current start_unix\n",
+ "\n",
+ " # rhist의 마지막 행에 도달할 때까지 반복\n",
+ " while True:\n",
+ " n = rhist[rhist.start_unix==curr_unix].index[0]\n",
+ " cycle = rhist.loc[n, 'cycle']\n",
+ " D_n = rhist.loc[n, 'D_n']\n",
+ " S_n = rhist.loc[n, 'S_n']\n",
+ " # 참값인 경우\n",
+ " if (abs(D_n - S_n) <= 5):\n",
+ " pass\n",
+ " # 참값이 아닌 경우\n",
+ " else:\n",
+ " # 2-1-1. 결측치 처리 : 인접한 두 start_unix의 차이가 계획된 주기의 두 배보다 크면 결측이 일어났다고 판단, 신호계획의 현시시간으로 \"대체\"\n",
+ " if curr_unix - prev_unix >= 2 * cycle:\n",
+ " # prev_unix를 계획된 주기만큼 늘려가면서 한 행씩 채워나간다.\n",
+ " # (curr_unix와의 차이가 계획된 주기보다 작거나 같아질 때까지)\n",
+ " new_rows = []\n",
+ " while curr_unix - prev_unix > cycle:\n",
+ " prev_unix += cycle\n",
+ " # 신호 계획(prow) 불러오기\n",
+ " start_seconds = np.array(timetable.start_seconds)\n",
+ " idx = (start_seconds <= prev_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[idx].start_hour\n",
+ " start_minute = timetable.iloc[idx].start_minute\n",
+ " prow = plan.copy()[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
+ " # prow에서 필요한 부분을 rhist에 추가\n",
+ " prow['start_unix'] = prev_unix\n",
+ " prow = prow.drop(['start_hour', 'start_minute', 'offset'], axis=1)\n",
+ " cycle = prow.iloc[0].cycle\n",
+ " rhist = pd.concat([rhist, prow])\n",
+ " rhist = rhist.sort_values(by='start_unix').reset_index(drop=True)\n",
+ " n += 1\n",
+ "\n",
+ " # 2-1-2. 이상치 처리 : 비율에 따라 해당 행을 \"삭제\"(R_n <= 0.5) 또는 \"조정\"(R_n > 0.5)한다\n",
+ " R_n = (curr_unix - prev_unix) / cycle # R_n : 비율\n",
+ " # R_n이 0.5보다 작거나 같으면 해당 행을 삭제\n",
+ " if R_n <= 0.5:\n",
+ " rhist = rhist.drop(index=n).reset_index(drop=True)\n",
+ " # 행삭제에 따른 curr_unix, R_n 재정의\n",
+ " curr_unix = rhist.loc[n, 'start_unix']\n",
+ " R_n = (curr_unix - prev_unix) / cycle # R_n : 비율\n",
+ "\n",
+ " # R_n이 0.5보다 크면 해당 행 조정 (비율을 유지한 채로 현시시간 대체)\n",
+ " if R_n > 0.5:\n",
+ " # 신호 계획(prow) 불러오기\n",
+ " start_seconds = np.array(timetable.start_seconds)\n",
+ " idx = (start_seconds <= curr_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[idx].start_hour\n",
+ " start_minute = timetable.iloc[idx].start_minute\n",
+ " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
+ " # 조정된 현시시간 (prow에 R_n을 곱하고 정수로 바꿈)\n",
+ " adjusted_dur = prow.copy()[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] * R_n\n",
+ " int_parts = adjusted_dur.iloc[0].apply(lambda x: int(x))\n",
+ " frac_parts = adjusted_dur.iloc[0] - int_parts\n",
+ " difference = round(adjusted_dur.iloc[0].sum()) - int_parts.sum()\n",
+ " for _ in range(difference): # 소수 부분이 가장 큰 상위 'difference'개의 값에 대해 올림 처리\n",
+ " max_frac_index = frac_parts.idxmax()\n",
+ " int_parts[max_frac_index] += 1\n",
+ " frac_parts[max_frac_index] = 0 # 이미 처리된 항목은 0으로 설정\n",
+ " # rhist에 조정된 현시시간을 반영\n",
+ " rhist.loc[n, [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] = int_parts.values\n",
+ " rhist.loc[n, 'cycle'] = int_parts.sum().sum() // 2\n",
+ "\n",
+ " if n == rhist.index[-1]:\n",
+ " break\n",
+ " prev_unix = curr_unix\n",
+ " curr_unix = rhist.loc[n+1, 'start_unix']\n",
+ " # rhist['start_dt'] = rhist['start_unix'].map(lambda x:datetime.fromtimestamp(x))\n",
+ "\n",
+ " # 생략해도 무방할 코드\n",
+ " rhist = rhist.reset_index(drop=True)\n",
+ " rhist = rhist.sort_values(by=['start_unix'])\n",
+ "\n",
+ " # D_n 및 S_n 값 재정의\n",
+ " for n in range(len(rhist)):\n",
+ " curr_unix = rhist.iloc[n].start_unix # current start_unix\n",
+ " rhist.loc[n, ['D_n', 'S_n']] = calculate_DS(rhist, curr_unix)\n",
+ " rhists.append(rhist)\n",
+ "rhists = pd.concat(rhists).sort_values(by=['start_unix','inter_no'])\n",
+ "rhists = rhists[rhists.start_unix >= present_time - 3600]\n",
+ "rhists = rhists.drop(columns=['D_n', 'S_n'])\n",
+ "rhists"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 34,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ " 0%| | 0/17280 [00:00, ?it/s]"
+ ]
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "100%|██████████| 17280/17280 [00:18<00:00, 929.46it/s] \n"
+ ]
+ }
+ ],
+ "source": [
+ "file_path = '../../Data/tables/movements/'\n",
+ "movements = [pd.read_csv(file_path + file, index_col=0) for file in tqdm(os.listdir(file_path))]\n",
+ "movements = pd.concat(movements).drop_duplicates()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " move_A | \n",
+ " move_B | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 8 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ " 15 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 7 | \n",
+ " 3 | \n",
+ "
\n",
+ " \n",
+ " 20 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 6 | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " 24 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 6 | \n",
+ " 2 | \n",
+ "
\n",
+ " \n",
+ " 26 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 5 | \n",
+ " 2 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phas_A phas_B move_A move_B\n",
+ "8 175 1 1 8 4\n",
+ "15 175 2 2 7 3\n",
+ "20 175 3 3 6 1\n",
+ "24 175 3 4 6 2\n",
+ "26 175 4 4 5 2"
+ ]
+ },
+ "execution_count": 20,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "movements_wo_start_unix_list = [] # movements without start_unix\n",
+ "for inter_no in sorted(movements.inter_no.unique()):\n",
+ " movements_wo_start_unix = movements[movements_wo_start_unix.inter_no==inter_no]\n",
+ " movements_wo_start_unix = movements_wo_start_unix[['inter_no', 'phas_A', 'phas_B', 'move_A', 'move_B']]\n",
+ " movements_wo_start_unix = movements_wo_start_unix.drop_duplicates().sort_values(by=['phas_A','phas_B'])\n",
+ " movements_wo_start_unix_list.append(movements_wo_start_unix)\n",
+ "movements_wo_start_unix = pd.concat(movements_wo_start_unix_list)\n",
+ "movements_wo_start_unix.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 67,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " start_unix | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " duration | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 178 | \n",
+ " 1704388800 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 38 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 178 | \n",
+ " 1704388800 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 178 | \n",
+ " 1704388800 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 40 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 178 | \n",
+ " 1704388800 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 23 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 201 | \n",
+ " 1704388800 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 24 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 767 | \n",
+ " 206 | \n",
+ " 1704392160 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 35 | \n",
+ "
\n",
+ " \n",
+ " 768 | \n",
+ " 206 | \n",
+ " 1704392160 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 26 | \n",
+ "
\n",
+ " \n",
+ " 769 | \n",
+ " 206 | \n",
+ " 1704392160 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 26 | \n",
+ "
\n",
+ " \n",
+ " 770 | \n",
+ " 202 | \n",
+ " 1704392211 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 39 | \n",
+ "
\n",
+ " \n",
+ " 771 | \n",
+ " 202 | \n",
+ " 1704392211 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 101 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
772 rows × 5 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no start_unix phas_A phas_B duration\n",
+ "0 178 1704388800 1 1 38\n",
+ "1 178 1704388800 2 2 39\n",
+ "2 178 1704388800 3 3 40\n",
+ "3 178 1704388800 4 4 23\n",
+ "4 201 1704388800 1 1 24\n",
+ ".. ... ... ... ... ...\n",
+ "767 206 1704392160 2 2 35\n",
+ "768 206 1704392160 3 3 26\n",
+ "769 206 1704392160 4 4 26\n",
+ "770 202 1704392211 1 1 39\n",
+ "771 202 1704392211 2 2 101\n",
+ "\n",
+ "[772 rows x 5 columns]"
+ ]
+ },
+ "execution_count": 67,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# 계층화된 형태로 변환\n",
+ "hrhists = [] # hierarchied recent history\n",
+ "for i, row in rhists.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_unix = row.start_unix\n",
+ "\n",
+ " ind = (timetable['start_seconds'] <= row.start_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[ind].start_hour\n",
+ " start_minute = timetable.iloc[ind].start_minute\n",
+ " isplit = isplits[(inter_no, start_hour, start_minute)]\n",
+ " phas_As = [isplit[j][0] for j in isplit.keys()]\n",
+ " phas_Bs = [isplit[j][1] for j in isplit.keys()]\n",
+ " durs_A = row[[f'dura_A{j}' for j in range(1,9)]]\n",
+ " durs_B = row[[f'dura_B{j}' for j in range(1,9)]]\n",
+ " durations = []\n",
+ " for j in range(1, len(isplit)+1):\n",
+ " ja = isplit[j][0]\n",
+ " jb = isplit[j][1]\n",
+ " if ja == jb:\n",
+ " durations.append(min(durs_A[ja-1], durs_B[jb-1]))\n",
+ " else:\n",
+ " durations.append(abs(durs_A[ja-1] - durs_B[ja-1]))\n",
+ " new_rows = pd.DataFrame({'inter_no':[inter_no] * len(durations), 'start_unix':[start_unix] * len(durations),\n",
+ " 'phas_A':phas_As, 'phas_B':phas_Bs, 'duration':durations})\n",
+ " hrhists.append(new_rows)\n",
+ "hrhists = pd.concat(hrhists)\n",
+ "hrhists = hrhists.sort_values(by = ['start_unix', 'inter_no', 'phas_A', 'phas_B']).reset_index(drop=True)\n",
+ "hrhists"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 133,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "movement = time2movement[present_time]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 138,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 중복을 제거하고 (inter_no, start_unix) 쌍을 만듭니다.\n",
+ "hrhists_inter_unix = set(hrhists[['inter_no', 'start_unix']].drop_duplicates().itertuples(index=False, name=None))\n",
+ "movement_inter_unix = set(movement[['inter_no', 'start_unix']].drop_duplicates().itertuples(index=False, name=None))\n",
+ "\n",
+ "# hrhists에는 있지만 movement에는 없는 (inter_no, start_unix) 쌍을 찾습니다.\n",
+ "missing_in_movement = hrhists_inter_unix - movement_inter_unix\n",
+ "\n",
+ "# 새로운 행들을 생성합니다.\n",
+ "new_rows = []\n",
+ "for inter_no, start_unix in missing_in_movement:\n",
+ " # movements_wo_start_unix에서 해당 inter_no의 데이터를 찾습니다.\n",
+ " new_row = movements_wo_start_unix[movements_wo_start_unix['inter_no'] == inter_no].copy()\n",
+ " # start_unix 값을 설정합니다.\n",
+ " new_row['start_unix'] = start_unix\n",
+ " new_rows.append(new_row)\n",
+ "\n",
+ "# 새로운 데이터프레임을 생성하고 기존 movement 데이터프레임과 합칩니다.\n",
+ "new_movement = pd.concat(new_rows, ignore_index=True)\n",
+ "movement_updated = pd.concat([movement, new_movement], ignore_index=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 143,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " node_id | \n",
+ " start_unix | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " duration | \n",
+ " inc_edge_A | \n",
+ " out_edge_A | \n",
+ " inc_edge_B | \n",
+ " out_edge_B | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704388801 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 36 | \n",
+ " -571542809_01 | \n",
+ " 571542811_01 | \n",
+ " 571542811_02 | \n",
+ " 571542809_01 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704388801 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 20 | \n",
+ " 571542811_02 | \n",
+ " 571542107_01 | \n",
+ " -571542809_01 | \n",
+ " 571542809_01 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704388801 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 68 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704388801 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 26 | \n",
+ " -571542809_01 | \n",
+ " 571542811_01 | \n",
+ " 571542107_02 | \n",
+ " 571542809_01 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 176 | \n",
+ " i1 | \n",
+ " 1704388850 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542810_01 | \n",
+ " -571542797_02.99 | \n",
+ " 571542797_02.99 | \n",
+ " 571542810_01 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 748 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704392160 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 35 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 749 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704392160 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 26 | \n",
+ " -571511538_02 | \n",
+ " 571542073_02 | \n",
+ " 571542073_01 | \n",
+ " 571511538_02 | \n",
+ "
\n",
+ " \n",
+ " 750 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704392160 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 26 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 751 | \n",
+ " 202 | \n",
+ " i9 | \n",
+ " 1704392211 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 39 | \n",
+ " 571510152_02 | \n",
+ " -571510152_01 | \n",
+ " 571510152_01 | \n",
+ " 571510152_01.65 | \n",
+ "
\n",
+ " \n",
+ " 752 | \n",
+ " 202 | \n",
+ " i9 | \n",
+ " 1704392211 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 101 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
757 rows × 10 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no node_id start_unix phas_A phas_B duration inc_edge_A \\\n",
+ "0 177 i2 1704388801 1 1 36 -571542809_01 \n",
+ "1 177 i2 1704388801 2 2 20 571542811_02 \n",
+ "2 177 i2 1704388801 3 3 68 NaN \n",
+ "3 177 i2 1704388801 4 4 26 -571542809_01 \n",
+ "4 176 i1 1704388850 1 1 37 -571542810_01 \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "748 206 i7 1704392160 2 2 35 NaN \n",
+ "749 206 i7 1704392160 3 3 26 -571511538_02 \n",
+ "750 206 i7 1704392160 4 4 26 NaN \n",
+ "751 202 i9 1704392211 1 1 39 571510152_02 \n",
+ "752 202 i9 1704392211 2 2 101 NaN \n",
+ "\n",
+ " out_edge_A inc_edge_B out_edge_B \n",
+ "0 571542811_01 571542811_02 571542809_01 \n",
+ "1 571542107_01 -571542809_01 571542809_01 \n",
+ "2 NaN NaN NaN \n",
+ "3 571542811_01 571542107_02 571542809_01 \n",
+ "4 -571542797_02.99 571542797_02.99 571542810_01 \n",
+ ".. ... ... ... \n",
+ "748 NaN NaN NaN \n",
+ "749 571542073_02 571542073_01 571511538_02 \n",
+ "750 NaN NaN NaN \n",
+ "751 -571510152_01 571510152_01 571510152_01.65 \n",
+ "752 NaN NaN NaN \n",
+ "\n",
+ "[757 rows x 10 columns]"
+ ]
+ },
+ "execution_count": 143,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "movedur = pd.merge(movement_updated, hrhists, how='inner', on=['inter_no', 'start_unix', 'phas_A', 'phas_B']) # movements and durations\n",
+ "movedur = movedur.sort_values(by=['start_unix', 'inter_no', 'phas_A','phas_B'])\n",
+ "movedur = movedur[['inter_no', 'start_unix', 'phas_A', 'phas_B', 'move_A', 'move_B', 'duration']]\n",
+ "\n",
+ "# 이동류 매칭 테이블에서 진입id, 진출id를 가져와서 붙임.\n",
+ "for i, row in movedur.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_unix = row.start_unix\n",
+ " # incoming and outgoing edges A\n",
+ " move_A = row.move_A\n",
+ " if move_A in [17, 18]:\n",
+ " inc_edge_A = np.nan\n",
+ " out_edge_A = np.nan\n",
+ " else:\n",
+ " match_A = matching[(matching.inter_no == inter_no) & (matching.move_no == move_A)].iloc[0]\n",
+ " inc_edge_A = match_A.inc_edge\n",
+ " out_edge_A = match_A.out_edge\n",
+ " movedur.loc[i, ['inc_edge_A', 'out_edge_A']] = [inc_edge_A, out_edge_A]\n",
+ " # incoming and outgoing edges B\n",
+ " move_B = row.move_B\n",
+ " if move_B in [17, 18]:\n",
+ " inc_edge_B = np.nan\n",
+ " out_edge_B = np.nan\n",
+ " else:\n",
+ " match_B = matching[(matching.inter_no == inter_no) & (matching.move_no == move_B)].iloc[0]\n",
+ " inc_edge_B = match_B.inc_edge\n",
+ " out_edge_B = match_B.out_edge\n",
+ " movedur.loc[i, ['inc_edge_B', 'out_edge_B']] = [inc_edge_B, out_edge_B]\n",
+ "\n",
+ "# 이동류 컬럼 제거\n",
+ "movedur = movedur.drop(['move_A', 'move_B'], axis=1)\n",
+ "\n",
+ "histid = movedur.copy() # history with edge ids (incoming and outgoing edge ids)\n",
+ "histid['node_id'] = histid['inter_no'].map(inter2node)\n",
+ "histid = histid[['inter_no', 'node_id', 'start_unix', 'phas_A', 'phas_B', 'duration', 'inc_edge_A', 'out_edge_A', 'inc_edge_B', 'out_edge_B']]\n",
+ "histid = histid[histid.start_unix > present_time - 3600]\n",
+ "histid"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 71,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2024-01-05 16:40:00\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " node_id | \n",
+ " start_unix | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " duration | \n",
+ " inc_edge_A | \n",
+ " out_edge_A | \n",
+ " inc_edge_B | \n",
+ " out_edge_B | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 202 | \n",
+ " i9 | \n",
+ " 1704436810 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 46 | \n",
+ " 571510152_02 | \n",
+ " -571510152_01 | \n",
+ " 571510152_01 | \n",
+ " 571510152_01.65 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 202 | \n",
+ " i9 | \n",
+ " 1704436810 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 114 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 178 | \n",
+ " i3 | \n",
+ " 1704436860 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 38 | \n",
+ " 571540304_02 | \n",
+ " 571556450_01 | \n",
+ " 571556450_02 | \n",
+ " 571540304_01 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 178 | \n",
+ " i3 | \n",
+ " 1704436860 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " 571556450_02 | \n",
+ " 571500475_01 | \n",
+ " 571540304_02 | \n",
+ " 571540303_01 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 178 | \n",
+ " i3 | \n",
+ " 1704436860 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 43 | \n",
+ " 571540303_02.21 | \n",
+ " 571556450_01 | \n",
+ " 571540303_02.21 | \n",
+ " 571500475_01 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 477 | \n",
+ " 202 | \n",
+ " i9 | \n",
+ " 1704440171 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 114 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 478 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704440171 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 45 | \n",
+ " -571511538_02 | \n",
+ " 571542073_02 | \n",
+ " 571542073_01 | \n",
+ " 571511538_02 | \n",
+ "
\n",
+ " \n",
+ " 479 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704440171 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 53 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 480 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704440171 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 26 | \n",
+ " -571511538_02 | \n",
+ " 571542073_02 | \n",
+ " 571542073_01 | \n",
+ " 571511538_02 | \n",
+ "
\n",
+ " \n",
+ " 481 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704440171 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 26 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
482 rows × 10 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no node_id start_unix phas_A phas_B duration inc_edge_A \\\n",
+ "0 202 i9 1704436810 1 1 46 571510152_02 \n",
+ "1 202 i9 1704436810 2 2 114 NaN \n",
+ "2 178 i3 1704436860 1 1 38 571540304_02 \n",
+ "3 178 i3 1704436860 2 2 39 571556450_02 \n",
+ "4 178 i3 1704436860 3 3 43 571540303_02.21 \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "477 202 i9 1704440171 2 2 114 NaN \n",
+ "478 206 i7 1704440171 1 1 45 -571511538_02 \n",
+ "479 206 i7 1704440171 2 2 53 NaN \n",
+ "480 206 i7 1704440171 3 3 26 -571511538_02 \n",
+ "481 206 i7 1704440171 4 4 26 NaN \n",
+ "\n",
+ " out_edge_A inc_edge_B out_edge_B \n",
+ "0 -571510152_01 571510152_01 571510152_01.65 \n",
+ "1 NaN NaN NaN \n",
+ "2 571556450_01 571556450_02 571540304_01 \n",
+ "3 571500475_01 571540304_02 571540303_01 \n",
+ "4 571556450_01 571540303_02.21 571500475_01 \n",
+ ".. ... ... ... \n",
+ "477 NaN NaN NaN \n",
+ "478 571542073_02 571542073_01 571511538_02 \n",
+ "479 NaN NaN NaN \n",
+ "480 571542073_02 571542073_01 571511538_02 \n",
+ "481 NaN NaN NaN \n",
+ "\n",
+ "[482 rows x 10 columns]"
+ ]
+ },
+ "execution_count": 71,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "m = 200\n",
+ "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
+ "present_time = fmins[m] # 현재시점\n",
+ "print(datetime.fromtimestamp(present_time))\n",
+ "\n",
+ "# (구) make_rhistory\n",
+ "Rhists = [] # Recent history (1시간 이내)\n",
+ "for inter_no in history.inter_no.unique():\n",
+ " # - 5분마다 신호이력 데이터 수집해서 통합테이블 생성할때\n",
+ " # 1. 조회시점의 유닉스 타임 이전의 신호이력 수집\n",
+ " rhistory = history.copy() # recent history\n",
+ " rhistory = rhistory[(rhistory.end_unix < present_time)]\n",
+ " hours = np.array(range(midnight, next_day + 1, 3600))\n",
+ " rhist = rhistory.copy()[rhistory.inter_no == inter_no] # 특정한 inter_no\n",
+ " rhist = rhist.reset_index(drop=True)\n",
+ " new_rows = []\n",
+ " # 1-1. 결측치 처리 : 인접한 두 end_unix의 차이가 계획된 주기의 두 배보다 크면 결측이 일어났다고 판단\n",
+ " for n in range(len(rhist) - 1):\n",
+ " curr_unix = rhist.iloc[n].end_unix # current end_unix\n",
+ " next_unix = rhist.iloc[n+1].end_unix # next end_unix\n",
+ " cycle = rhist.iloc[n].cycle\n",
+ " if next_unix - curr_unix >= 2 * cycle:\n",
+ " # 현재 unix를 계획된 주기만큼 늘려가면서 한 행씩 채워나간다.\n",
+ " #(다음 unix와의 차이가 계획된 주기보다 작거나 같아질 때까지)\n",
+ " while next_unix - curr_unix > cycle:\n",
+ " curr_unix += cycle\n",
+ " start_seconds = np.array(timetable.start_seconds)\n",
+ " idx = (start_seconds <= curr_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[idx].start_hour\n",
+ " start_minute = timetable.iloc[idx].start_minute\n",
+ " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
+ " prow = prow.drop(['start_hour', 'start_minute'], axis=1)\n",
+ " prow['end_unix'] = curr_unix\n",
+ " cycle = prow.iloc[0].cycle\n",
+ " new_rows.append(prow)\n",
+ " rhist = pd.concat([rhist] + new_rows).sort_values(['end_unix'])\n",
+ " rhist = rhist.reset_index(drop=True)\n",
+ "\n",
+ " # 1-2. 이상치 처리 : 기준유닉스로부터의 시간차이와 현시시간합이 11 이상 차이나면 이상치가 발생했다고 판단\n",
+ " Rhist = rhist.copy() # recent history 1704393231\n",
+ " Rhist = Rhist[(Rhist.end_unix >= present_time - 3600)] # Recent history (1시간 이내)\n",
+ " Rhist = Rhist.reset_index(drop=True)\n",
+ " Rhist['D_n'] = 0\n",
+ " Rhist['S_n'] = 0\n",
+ " for n in range(len(Rhist)):\n",
+ " curr_unix = Rhist.iloc[n].end_unix # current end_unix\n",
+ " cycle = Rhist.iloc[n].cycle\n",
+ " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
+ " end_unixes = rhist.end_unix.unique()\n",
+ " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
+ " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
+ " # D_n : 시간차이 \n",
+ " D_n = curr_unix - base_unix\n",
+ " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " # S_n : 현시시간합\n",
+ " S_n = ddurations.values.sum() // 2\n",
+ " Rhist.loc[n, ['D_n', 'S_n']] = [D_n, S_n]\n",
+ " n = 1\n",
+ " while n < len(Rhist):\n",
+ " prev_unix = Rhist[Rhist.index==n-1]['end_unix'].iloc[0] # previous end_unix\n",
+ " curr_unix = Rhist[Rhist.index==n]['end_unix'].iloc[0] # current end_unix\n",
+ " R_n = (curr_unix - prev_unix) / cycle\n",
+ " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
+ " end_unixes = rhist.end_unix.unique()\n",
+ " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
+ " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
+ " # D_n : 시간차이\n",
+ " D_n = curr_unix - base_unix\n",
+ " # S_n : 현시시간합\n",
+ " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " S_n = ddurations.values.sum() // 2\n",
+ " # 비율이 0.5보다 작거나 같으면 해당 행을 삭제\n",
+ " if (abs(D_n - S_n) > 10) & (R_n <= 0.5):\n",
+ " Rhist = Rhist.drop(index=n)\n",
+ " n += 1\n",
+ " # 행삭제에 따른 curr_unix, D_n, S_n 등 재정의\n",
+ " if not Rhist[Rhist.index==n]['end_unix'].empty: # 마지막 행을 삭제하여 뒤의 행이 없을 때를 대비\n",
+ " curr_unix = Rhist[Rhist.index==n]['end_unix'].iloc[0] # current end_unix\n",
+ " R_n = (curr_unix - prev_unix) / cycle\n",
+ " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
+ " end_unixes = rhist.end_unix.unique()\n",
+ " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
+ " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
+ " # D_n : 시간차이\n",
+ " D_n = curr_unix - base_unix\n",
+ " # S_n : 현시시간합\n",
+ " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " S_n = ddurations.values.sum() // 2\n",
+ " # 비율이 0.5보다 크면 해당 행 조정 (비율을 유지한 채로 현시시간 대체)\n",
+ " if (abs(D_n - S_n) > 10) & (R_n > 0.5):\n",
+ " start_seconds = np.array(timetable.start_seconds)\n",
+ " idx = (start_seconds <= curr_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[idx].start_hour\n",
+ " start_minute = timetable.iloc[idx].start_minute\n",
+ " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)].copy().reset_index(drop=True).iloc[0] # planned row\n",
+ " adjusted_dur = prow[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] * R_n\n",
+ " # 조정된 현시시간을 정수로 바꿈\n",
+ " int_parts = adjusted_dur.apply(lambda x: int(x))\n",
+ " frac_parts = adjusted_dur - int_parts\n",
+ " difference = int(round(adjusted_dur.sum())) - int_parts.sum()\n",
+ " # 소수 부분이 가장 큰 상위 'difference'개의 값에 대해 올림 처리\n",
+ " for _ in range(difference):\n",
+ " max_frac_index = frac_parts.idxmax()\n",
+ " int_parts[max_frac_index] += 1\n",
+ " frac_parts[max_frac_index] = 0 # 이미 처리된 항목은 0으로 설정\n",
+ " Rhist.loc[n, [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] = int_parts.values\n",
+ " Rhist.loc[n, 'cycle'] = int_parts.sum() // 2\n",
+ " n += 1\n",
+ " Rhist = Rhist.drop(columns=['offset', 'D_n', 'S_n'])\n",
+ " Rhists.append(Rhist)\n",
+ "Rhists = pd.concat(Rhists)\n",
+ "Rhists = Rhists.sort_values(by=['end_unix', 'inter_no']).reset_index(drop=True)\n",
+ "\n",
+ "# (구) make_histid\n",
+ "# 2. 시작 유닉스 타임컬럼 생성 후 종류 유닉스 타임에서 현시별 현시기간 컬럼의 합을 뺀 값으로 입력\n",
+ "# - 현시시간의 합을 뺀 시간의 +- 10초 이내에 이전 주기정보가 존재하면 그 유닉스 시간을 시작 유닉스시간 값으로 하고, 존재하지 않으면 현시시간의 합을 뺀 유닉스 시간을 시작 유닉스 시간으로 지정\n",
+ "for i, row in rhistory.iterrows():\n",
+ " # 이전 유닉스 존재하지 않음 => 현시시간 합의 차\n",
+ " # 이전 유닉스 존재, abs < 10 => 이전 유닉스\n",
+ " # 이전 유닉스 존재, abs >=10 => 현시시간 합의 차\n",
+ " inter_no = row.inter_no\n",
+ " end_unix = row.end_unix\n",
+ " elapsed_time = row[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]].sum() // 2 # 현시시간 합\n",
+ " start_unix = end_unix - elapsed_time\n",
+ " pre_rows = history[:i] # previous rows\n",
+ " if inter_no in pre_rows.inter_no.unique(): # 이전 유닉스 존재\n",
+ " pre_unix = pre_rows[pre_rows.inter_no == inter_no]['end_unix'].iloc[-1] # previous unix time\n",
+ " if abs(pre_unix - start_unix) < 10: # abs < 10\n",
+ " start_unix = pre_unix\n",
+ " else: # abs >= 10\n",
+ " pass\n",
+ " rhistory.loc[i, 'start_unix'] = start_unix \n",
+ "rhistory[rhistory.isna()] = 0\n",
+ "rhistory['start_unix'] = rhistory['start_unix'].astype(int)\n",
+ "rhistory = rhistory[['inter_no', 'start_unix'] + [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)] + ['cycle']]\n",
+ "\n",
+ "# 계층화된 형태로 변환\n",
+ "hrhistory = [] # hierarchized recent history\n",
+ "for i, row in rhistory.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_unix = row.start_unix\n",
+ "\n",
+ " ind = (timetable['start_seconds'] <= row.start_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[ind].start_hour\n",
+ " start_minute = timetable.iloc[ind].start_minute\n",
+ " isplit = isplits[(inter_no, start_hour, start_minute)]\n",
+ " phas_As = [isplit[j][0] for j in isplit.keys()]\n",
+ " phas_Bs = [isplit[j][1] for j in isplit.keys()]\n",
+ " durs_A = row[[f'dura_A{j}' for j in range(1,9)]]\n",
+ " durs_B = row[[f'dura_B{j}' for j in range(1,9)]]\n",
+ " durations = []\n",
+ " for j in range(1, len(isplit)+1):\n",
+ " ja = isplit[j][0]\n",
+ " jb = isplit[j][1]\n",
+ " if ja == jb:\n",
+ " durations.append(min(durs_A[ja-1], durs_B[jb-1]))\n",
+ " else:\n",
+ " durations.append(abs(durs_A[ja-1] - durs_B[ja-1]))\n",
+ " new_rows = pd.DataFrame({'inter_no':[inter_no] * len(durations), 'start_unix':[start_unix] * len(durations),\n",
+ " 'phas_A':phas_As, 'phas_B':phas_Bs, 'duration':durations})\n",
+ " hrhistory.append(new_rows)\n",
+ "hrhistory = pd.concat(hrhistory)\n",
+ "hrhistory = hrhistory.sort_values(by = ['start_unix', 'inter_no', 'phas_A', 'phas_B']).reset_index(drop=True)\n",
+ "\n",
+ "# 5초단위로 수집한 이동류정보(time2movement[present_time])와 최근 1시간 신호이력(hrhistory)을 병합\n",
+ "movedur = pd.merge(time2movement[present_time], hrhistory, how='inner', on=['inter_no', 'start_unix', 'phas_A', 'phas_B']) # movements and durations\n",
+ "movedur = movedur.sort_values(by=['start_unix', 'inter_no', 'phas_A','phas_B'])\n",
+ "movedur = movedur[['inter_no', 'start_unix', 'phas_A', 'phas_B', 'move_A', 'move_B', 'duration']]\n",
+ "\n",
+ "# 이동류 매칭 테이블에서 진입id, 진출id를 가져와서 붙임.\n",
+ "for i, row in movedur.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_unix = row.start_unix\n",
+ " # incoming and outgoing edges A\n",
+ " move_A = row.move_A\n",
+ " if move_A in [17, 18]:\n",
+ " inc_edge_A = np.nan\n",
+ " out_edge_A = np.nan\n",
+ " else:\n",
+ " match_A = matching[(matching.inter_no == inter_no) & (matching.move_no == move_A)].iloc[0]\n",
+ " inc_edge_A = match_A.inc_edge\n",
+ " out_edge_A = match_A.out_edge\n",
+ " movedur.loc[i, ['inc_edge_A', 'out_edge_A']] = [inc_edge_A, out_edge_A]\n",
+ " # incoming and outgoing edges B\n",
+ " move_B = row.move_B\n",
+ " if move_B in [17, 18]:\n",
+ " inc_edge_B = np.nan\n",
+ " out_edge_B = np.nan\n",
+ " else:\n",
+ " match_B = matching[(matching.inter_no == inter_no) & (matching.move_no == move_B)].iloc[0]\n",
+ " inc_edge_B = match_B.inc_edge\n",
+ " out_edge_B = match_B.out_edge\n",
+ " movedur.loc[i, ['inc_edge_B', 'out_edge_B']] = [inc_edge_B, out_edge_B]\n",
+ "\n",
+ "# 이동류 컬럼 제거\n",
+ "movedur = movedur.drop(['move_A', 'move_B'], axis=1)\n",
+ "\n",
+ "histid = movedur.copy() # history with edge ids (incoming and outgoing edge ids)\n",
+ "histid['node_id'] = histid['inter_no'].map(inter2node)\n",
+ "histid = histid[['inter_no', 'node_id', 'start_unix', 'phas_A', 'phas_B', 'duration', 'inc_edge_A', 'out_edge_A', 'inc_edge_B', 'out_edge_B']]\n",
+ "histid = histid[histid.start_unix > present_time - 3600]\n",
+ "# 시뮬레이션 시작시각 : 현재시각 - 600\n",
+ "# 시뮬레이션 종료시각 : 현재시각 - 300\n",
+ "# 현재시각 : present_time, PT\n",
+ "# PT-900 ... PT-600 ... PT-300 ... PT\n",
+ "histid"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2024-01-05 04:10:00\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " node_id | \n",
+ " start_unix | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " duration | \n",
+ " inc_edge_A | \n",
+ " out_edge_A | \n",
+ " inc_edge_B | \n",
+ " out_edge_B | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 176 | \n",
+ " i1 | \n",
+ " 1704391850 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542810_01 | \n",
+ " -571542797_02.99 | \n",
+ " 571542797_02.99 | \n",
+ " 571542810_01 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 176 | \n",
+ " i1 | \n",
+ " 1704391850 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 73 | \n",
+ " -571542810_01 | \n",
+ " -571542797_02.99 | \n",
+ " -571542810_01 | \n",
+ " 571543469_01 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 176 | \n",
+ " i1 | \n",
+ " 1704391850 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 40 | \n",
+ " 571543469_02 | \n",
+ " -571542797_02.99 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 178 | \n",
+ " i3 | \n",
+ " 1704391880 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 38 | \n",
+ " 571540304_02 | \n",
+ " 571556450_01 | \n",
+ " 571556450_02 | \n",
+ " 571540304_01 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 178 | \n",
+ " i3 | \n",
+ " 1704391880 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " 571556450_02 | \n",
+ " 571500475_01 | \n",
+ " 571540304_02 | \n",
+ " 571540303_01 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 528 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704395250 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 24 | \n",
+ " -571500569_01 | \n",
+ " 571500583_02 | \n",
+ " -571500569_01 | \n",
+ " 571500618_01 | \n",
+ "
\n",
+ " \n",
+ " 529 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704395250 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 24 | \n",
+ " 571500618_02 | \n",
+ " 571500583_02 | \n",
+ " 571500618_02 | \n",
+ " 571500617_01 | \n",
+ "
\n",
+ " \n",
+ " 530 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704395250 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 17 | \n",
+ " 571500617_02 | \n",
+ " 571500618_01 | \n",
+ " 571500618_02 | \n",
+ " 571500617_01 | \n",
+ "
\n",
+ " \n",
+ " 531 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704395250 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 58 | \n",
+ " 571500617_02 | \n",
+ " 571500618_01 | \n",
+ " 571500617_02 | \n",
+ " 571500569_01 | \n",
+ "
\n",
+ " \n",
+ " 532 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704395250 | \n",
+ " 5 | \n",
+ " 5 | \n",
+ " 17 | \n",
+ " 571500583_01 | \n",
+ " 571500617_01 | \n",
+ " 571500583_01 | \n",
+ " 571500569_01 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
533 rows × 10 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no node_id start_unix phas_A phas_B duration inc_edge_A \\\n",
+ "0 176 i1 1704391850 1 1 37 -571542810_01 \n",
+ "1 176 i1 1704391850 2 2 73 -571542810_01 \n",
+ "2 176 i1 1704391850 3 3 40 571543469_02 \n",
+ "3 178 i3 1704391880 1 1 38 571540304_02 \n",
+ "4 178 i3 1704391880 2 2 39 571556450_02 \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "528 201 i8 1704395250 1 1 24 -571500569_01 \n",
+ "529 201 i8 1704395250 2 2 24 571500618_02 \n",
+ "530 201 i8 1704395250 3 3 17 571500617_02 \n",
+ "531 201 i8 1704395250 4 4 58 571500617_02 \n",
+ "532 201 i8 1704395250 5 5 17 571500583_01 \n",
+ "\n",
+ " out_edge_A inc_edge_B out_edge_B \n",
+ "0 -571542797_02.99 571542797_02.99 571542810_01 \n",
+ "1 -571542797_02.99 -571542810_01 571543469_01 \n",
+ "2 -571542797_02.99 NaN NaN \n",
+ "3 571556450_01 571556450_02 571540304_01 \n",
+ "4 571500475_01 571540304_02 571540303_01 \n",
+ ".. ... ... ... \n",
+ "528 571500583_02 -571500569_01 571500618_01 \n",
+ "529 571500583_02 571500618_02 571500617_01 \n",
+ "530 571500618_01 571500618_02 571500617_01 \n",
+ "531 571500618_01 571500617_02 571500569_01 \n",
+ "532 571500617_01 571500583_01 571500569_01 \n",
+ "\n",
+ "[533 rows x 10 columns]"
+ ]
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "make_histid(50)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " end_unix | \n",
+ " dura_A1 | \n",
+ " dura_A2 | \n",
+ " dura_A3 | \n",
+ " dura_A4 | \n",
+ " dura_A5 | \n",
+ " dura_A6 | \n",
+ " dura_A7 | \n",
+ " dura_A8 | \n",
+ " ... | \n",
+ " dura_B3 | \n",
+ " dura_B4 | \n",
+ " dura_B5 | \n",
+ " dura_B6 | \n",
+ " dura_B7 | \n",
+ " dura_B8 | \n",
+ " cycle | \n",
+ " offset | \n",
+ " D_n | \n",
+ " S_n | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 202 | \n",
+ " 1704380540 | \n",
+ " 39 | \n",
+ " 101 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " ... | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ " 103 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 202 | \n",
+ " 1704380680 | \n",
+ " 39 | \n",
+ " 101 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " ... | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ " 103 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 202 | \n",
+ " 1704380820 | \n",
+ " 39 | \n",
+ " 101 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " ... | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ " 103 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 202 | \n",
+ " 1704380960 | \n",
+ " 39 | \n",
+ " 101 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " ... | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ " 103 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 202 | \n",
+ " 1704381100 | \n",
+ " 39 | \n",
+ " 101 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " ... | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ " 103 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 200 | \n",
+ " 202 | \n",
+ " 1704409679 | \n",
+ " 46 | \n",
+ " 114 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " ... | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ " 103 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 201 | \n",
+ " 202 | \n",
+ " 1704409840 | \n",
+ " 46 | \n",
+ " 114 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " ... | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ " 103 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 202 | \n",
+ " 202 | \n",
+ " 1704410000 | \n",
+ " 46 | \n",
+ " 114 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " ... | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ " 103 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 203 | \n",
+ " 202 | \n",
+ " 1704410160 | \n",
+ " 46 | \n",
+ " 114 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " ... | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ " 103 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ " 204 | \n",
+ " 202 | \n",
+ " 1704410320 | \n",
+ " 46 | \n",
+ " 114 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " ... | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ " 103 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
205 rows × 22 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no end_unix dura_A1 dura_A2 dura_A3 dura_A4 dura_A5 \\\n",
+ "0 202 1704380540 39 101 0 0 0 \n",
+ "1 202 1704380680 39 101 0 0 0 \n",
+ "2 202 1704380820 39 101 0 0 0 \n",
+ "3 202 1704380960 39 101 0 0 0 \n",
+ "4 202 1704381100 39 101 0 0 0 \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "200 202 1704409679 46 114 0 0 0 \n",
+ "201 202 1704409840 46 114 0 0 0 \n",
+ "202 202 1704410000 46 114 0 0 0 \n",
+ "203 202 1704410160 46 114 0 0 0 \n",
+ "204 202 1704410320 46 114 0 0 0 \n",
+ "\n",
+ " dura_A6 dura_A7 dura_A8 ... dura_B3 dura_B4 dura_B5 dura_B6 \\\n",
+ "0 0 0 0 ... 0 0 0 0 \n",
+ "1 0 0 0 ... 0 0 0 0 \n",
+ "2 0 0 0 ... 0 0 0 0 \n",
+ "3 0 0 0 ... 0 0 0 0 \n",
+ "4 0 0 0 ... 0 0 0 0 \n",
+ ".. ... ... ... ... ... ... ... ... \n",
+ "200 0 0 0 ... 0 0 0 0 \n",
+ "201 0 0 0 ... 0 0 0 0 \n",
+ "202 0 0 0 ... 0 0 0 0 \n",
+ "203 0 0 0 ... 0 0 0 0 \n",
+ "204 0 0 0 ... 0 0 0 0 \n",
+ "\n",
+ " dura_B7 dura_B8 cycle offset D_n S_n \n",
+ "0 0 0 140 103 0 0 \n",
+ "1 0 0 140 103 0 0 \n",
+ "2 0 0 140 103 0 0 \n",
+ "3 0 0 140 103 0 0 \n",
+ "4 0 0 140 103 0 0 \n",
+ ".. ... ... ... ... ... ... \n",
+ "200 0 0 160 103 0 0 \n",
+ "201 0 0 160 103 0 0 \n",
+ "202 0 0 160 103 0 0 \n",
+ "203 0 0 160 103 0 0 \n",
+ "204 0 0 160 103 0 0 \n",
+ "\n",
+ "[205 rows x 22 columns]"
+ ]
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "m = 100\n",
+ "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
+ "present_time = fmins[m] # 현재시점\n",
+ "\n",
+ "# 1. 신호이력 데이터 수집\n",
+ "rhistory = history.copy()[(history.end_unix < present_time)]\n",
+ "rhistory = rhistory.reset_index(drop=True)\n",
+ "hours = np.array(range(midnight, next_day + 1, 3600))\n",
+ "rhist = rhistory.copy()[rhistory.inter_no == inter_no] # 특정한 inter_no\n",
+ "rhist = rhist.reset_index(drop=True)\n",
+ "rhist['D_n'] = 0 # D_n : 시간차이\n",
+ "rhist['S_n'] = 0 # S_n : 현시시간합\n",
+ "rhist"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 43,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2024-01-05 08:19:00\n",
+ "2024-01-05 07:20:20\n"
+ ]
+ }
+ ],
+ "source": [
+ "movement = time2movement[present_time]\n",
+ "max_unix = movement.start_unix.max()\n",
+ "min_unix = movement.start_unix.min()\n",
+ "print(datetime.fromtimestamp(max_unix))\n",
+ "print(datetime.fromtimestamp(min_unix))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " move_A | \n",
+ " move_B | \n",
+ " start_unix | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 201 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " 3 | \n",
+ " 1704406820 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 201 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 5 | \n",
+ " 2 | \n",
+ " 1704406820 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 201 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 6 | \n",
+ " 2 | \n",
+ " 1704406820 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 201 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 6 | \n",
+ " 1 | \n",
+ " 1704406820 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 201 | \n",
+ " 5 | \n",
+ " 5 | \n",
+ " 7 | \n",
+ " 4 | \n",
+ " 1704406820 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 598 | \n",
+ " 202 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 6 | \n",
+ " 2 | \n",
+ " 1704410320 | \n",
+ "
\n",
+ " \n",
+ " 599 | \n",
+ " 202 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 17 | \n",
+ " 18 | \n",
+ " 1704410320 | \n",
+ "
\n",
+ " \n",
+ " 600 | \n",
+ " 201 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " 3 | \n",
+ " 1704410340 | \n",
+ "
\n",
+ " \n",
+ " 601 | \n",
+ " 201 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 5 | \n",
+ " 2 | \n",
+ " 1704410340 | \n",
+ "
\n",
+ " \n",
+ " 602 | \n",
+ " 201 | \n",
+ " 5 | \n",
+ " 5 | \n",
+ " 7 | \n",
+ " 4 | \n",
+ " 1704410340 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
603 rows × 6 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phas_A phas_B move_A move_B start_unix\n",
+ "0 201 1 1 8 3 1704406820\n",
+ "1 201 2 2 5 2 1704406820\n",
+ "2 201 3 3 6 2 1704406820\n",
+ "3 201 4 4 6 1 1704406820\n",
+ "4 201 5 5 7 4 1704406820\n",
+ ".. ... ... ... ... ... ...\n",
+ "598 202 1 1 6 2 1704410320\n",
+ "599 202 2 2 17 18 1704410320\n",
+ "600 201 1 1 8 3 1704410340\n",
+ "601 201 2 2 5 2 1704410340\n",
+ "602 201 5 5 7 4 1704410340\n",
+ "\n",
+ "[603 rows x 6 columns]"
+ ]
+ },
+ "execution_count": 25,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
+ "present_time = fmins[m] # 현재시점\n",
+ "print(datetime.fromtimestamp(present_time))\n",
+ "\n",
+ "Rhists = [] # Recent history (1시간 이내)\n",
+ "for inter_no in history.inter_no.unique():\n",
+ " # - 5분마다 신호이력 데이터 수집해서 통합테이블 생성할때\n",
+ " # 1. 조회시점의 유닉스 타임을 기준으로 신호이력의 유닉스 타임이 1시간 이내인(Rhist) 데이터 수집\n",
+ " rhistory = history.copy() # recent history\n",
+ " rhistory = rhistory[(rhistory.end_unix < present_time)]\n",
+ " hours = np.array(range(midnight, next_day + 1, 3600))\n",
+ " rhist = rhistory.copy()[rhistory.inter_no == inter_no] # 특정한 inter_no\n",
+ " rhist = rhist.reset_index(drop=True)\n",
+ " new_rows = []\n",
+ " # 1-1. 결측치 처리 : 인접한 두 end_unix의 차이가 계획된 주기의 두 배보다 크면 결측이 일어났다고 판단\n",
+ " for n in range(len(rhist) - 1):\n",
+ " curr_unix = rhist.iloc[n].end_unix # current end_unix\n",
+ " next_unix = rhist.iloc[n+1].end_unix # next end_unix\n",
+ " cycle = rhist.iloc[n].cycle\n",
+ " if next_unix - curr_unix >= 2 * cycle:\n",
+ " # 현재 unix를 계획된 주기만큼 늘려가면서 한 행씩 채워나간다.\n",
+ " #(다음 unix와의 차이가 계획된 주기보다 작거나 같아질 때까지)\n",
+ " while next_unix - curr_unix > cycle:\n",
+ " curr_unix += cycle \n",
+ " start_seconds = np.array(timetable.start_seconds)\n",
+ " idx = (start_seconds <= curr_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[idx].start_hour\n",
+ " start_minute = timetable.iloc[idx].start_minute\n",
+ " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
+ " prow = prow.drop(['start_hour', 'start_minute'], axis=1)\n",
+ " prow['end_unix'] = curr_unix\n",
+ " cycle = prow.iloc[0].cycle\n",
+ " new_rows.append(prow)\n",
+ " rhist = pd.concat([rhist] + new_rows).sort_values(['end_unix'])\n",
+ " rhist = rhist.reset_index(drop=True)\n",
+ "\n",
+ " # 1-2. 이상치 처리 : 기준유닉스로부터의 시간차이와 현시시간합이 11 이상 차이나면 이상치가 발생했다고 판단\n",
+ " Rhist = rhist.copy() # recent history 1704393231\n",
+ " Rhist = Rhist[(Rhist.end_unix >= present_time - 3600)] # Recent history (1시간 이내)\n",
+ " Rhist = Rhist.reset_index(drop=True)\n",
+ " Rhist['D_n'] = 0\n",
+ " Rhist['S_n'] = 0\n",
+ " for n in range(len(Rhist)):\n",
+ " curr_unix = Rhist.iloc[n].end_unix # current end_unix\n",
+ " cycle = Rhist.iloc[n].cycle\n",
+ " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
+ " end_unixes = rhist.end_unix.unique()\n",
+ " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
+ " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
+ " # D_n : 시간차이\n",
+ " D_n = curr_unix - base_unix\n",
+ " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " # S_n : 현시시간합\n",
+ " S_n = ddurations.values.sum() // 2\n",
+ " Rhist.loc[n, ['D_n', 'S_n']] = [D_n, S_n]\n",
+ " n = 1\n",
+ " while n < len(Rhist):\n",
+ " prev_unix = Rhist[Rhist.index==n-1]['end_unix'].iloc[0] # previous end_unix\n",
+ " curr_unix = Rhist[Rhist.index==n]['end_unix'].iloc[0] # current end_unix\n",
+ " R_n = (curr_unix - prev_unix) / cycle\n",
+ " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
+ " end_unixes = rhist.end_unix.unique()\n",
+ " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
+ " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
+ " # D_n : 시간차이\n",
+ " D_n = curr_unix - base_unix\n",
+ " # S_n : 현시시간합\n",
+ " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " S_n = ddurations.values.sum() // 2\n",
+ " # 비율이 0.5보다 작거나 같으면 해당 행을 삭제\n",
+ " if (abs(D_n - S_n) > 10) & (R_n <= 0.5):\n",
+ " # print(\"lt\", inter_no, curr_unix, round(R_n,2), D_n, S_n)\n",
+ " # display(Rhist.iloc[n])\n",
+ " Rhist = Rhist.drop(index=n)\n",
+ " n += 1\n",
+ " # 행삭제에 따른 curr_unix, D_n, S_n 등 재정의\n",
+ " if not Rhist[Rhist.index==n]['end_unix'].empty: # 마지막 행을 삭제하여 뒤의 행이 없을 때를 대비\n",
+ " curr_unix = Rhist[Rhist.index==n]['end_unix'].iloc[0] # current end_unix\n",
+ " R_n = (curr_unix - prev_unix) / cycle\n",
+ " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
+ " end_unixes = rhist.end_unix.unique()\n",
+ " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
+ " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
+ " # D_n : 시간차이\n",
+ " D_n = curr_unix - base_unix\n",
+ " # S_n : 현시시간합\n",
+ " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " S_n = ddurations.values.sum() // 2\n",
+ " # 비율이 0.5보다 크면 해당 행 조정 (비율을 유지한 채로 현시시간 대체)\n",
+ " if (abs(D_n - S_n) > 10) & (R_n > 0.5):\n",
+ " start_seconds = np.array(timetable.start_seconds)\n",
+ " idx = (start_seconds <= curr_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[idx].start_hour\n",
+ " start_minute = timetable.iloc[idx].start_minute\n",
+ " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)].copy().reset_index(drop=True).iloc[0] # planned row\n",
+ " adjusted_dur = prow[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] * R_n\n",
+ " # 조정된 현시시간을 정수로 바꿈\n",
+ " int_parts = adjusted_dur.apply(lambda x: int(x))\n",
+ " frac_parts = adjusted_dur - int_parts\n",
+ " difference = int(round(adjusted_dur.sum())) - int_parts.sum()\n",
+ " # 소수 부분이 가장 큰 상위 'difference'개의 값에 대해 올림 처리\n",
+ " for _ in range(difference):\n",
+ " max_frac_index = frac_parts.idxmax()\n",
+ " int_parts[max_frac_index] += 1\n",
+ " frac_parts[max_frac_index] = 0 # 이미 처리된 항목은 0으로 설정\n",
+ " Rhist.loc[n, [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] = int_parts.values\n",
+ " Rhist.loc[n, 'cycle'] = int_parts.sum() // 2\n",
+ " # print(\"gt\", inter_no, curr_unix, round(R_n,2), D_n, S_n)\n",
+ " n += 1\n",
+ " Rhist = Rhist.drop(columns=['offset', 'D_n', 'S_n'])\n",
+ " Rhists.append(Rhist)\n",
+ "Rhists = pd.concat(Rhists)\n",
+ "Rhists = Rhists.sort_values(by=['end_unix', 'inter_no']).reset_index(drop=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " start_hour | \n",
+ " start_minute | \n",
+ " start_seconds | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1704380400 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 7 | \n",
+ " 0 | \n",
+ " 1704405600 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 9 | \n",
+ " 0 | \n",
+ " 1704412800 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 18 | \n",
+ " 30 | \n",
+ " 1704447000 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " start_hour start_minute start_seconds\n",
+ "0 0 0 1704380400\n",
+ "1 7 0 1704405600\n",
+ "2 9 0 1704412800\n",
+ "3 18 30 1704447000"
+ ]
+ },
+ "execution_count": 16,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# split, isplit : A,B 분리 혹은 통합시 사용될 수 있는 딕셔너리\n",
+ "splits = {} # splits maps (inter_no, start_hour, start_minute) to split\n",
+ "for i, row in plan.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_hour = row.start_hour\n",
+ " start_minute = row.start_minute\n",
+ " cycle = row.cycle\n",
+ " cums_A = row[[f'dura_A{j}' for j in range(1,9)]].cumsum()\n",
+ " cums_B = row[[f'dura_B{j}' for j in range(1,9)]].cumsum()\n",
+ " splits[(inter_no, start_hour, start_minute)] = {} # split maps (phas_A, phas_B) to k\n",
+ " k = 0\n",
+ " for t in range(cycle):\n",
+ " new_phas_A = len(cums_A[cums_A < t]) + 1\n",
+ " new_phas_B = len(cums_B[cums_B < t]) + 1\n",
+ " if k == 0 or ((new_phas_A, new_phas_B) != (phas_A, phas_B)):\n",
+ " k += 1\n",
+ " phas_A = new_phas_A\n",
+ " phas_B = new_phas_B\n",
+ " splits[(inter_no, start_hour, start_minute)][(phas_A, phas_B)] = k\n",
+ "\n",
+ "isplits = {} # the inverse of splits\n",
+ "for i in splits:\n",
+ " isplits[i] = {splits[i][k]:k for k in splits[i]} # isplit maps k to (phas_A, phas_B)\n",
+ "\n",
+ "# timetable\n",
+ "timetable = plan[['start_hour', 'start_minute']].drop_duplicates()\n",
+ "timetable['start_seconds'] = midnight + timetable['start_hour'] * 3600 + timetable['start_minute'] * 60\n",
+ "timetable"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_rhistory(m:int):\n",
+ " '''\n",
+ " input : m\n",
+ " - m ranges from 0 to 287, but 0 makes an error where 288 = 86400//300\n",
+ " - present_time = fmins[m] : 현재시점\n",
+ " + fmins[m-2] : 시뮬레이션 시작시점\n",
+ " + fmins[m-1] : 시뮬레이션 종료시점\n",
+ " output : rhistory\n",
+ " - recent history\n",
+ " - 현재시각(present_time) 이전 1시간 동안의 신호이력에 대하여 결측치 및 이상치를 처리한 결과\n",
+ " - 교차로번호(inter_no), 종료유닉스(end_unix), 현시시간(dur_Aj, dur_Bj), 주기(cycle), 옵셋(offset)\n",
+ " '''\n",
+ " fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
+ " present_time = fmins[m] # 현재시점\n",
+ " print(datetime.fromtimestamp(present_time))\n",
+ "\n",
+ " Rhists = [] # Recent history (1시간 이내)\n",
+ " for inter_no in history.inter_no.unique():\n",
+ " # - 5분마다 신호이력 데이터 수집해서 통합테이블 생성할때\n",
+ " # 1. 조회시점의 유닉스 타임을 기준으로 신호이력의 유닉스 타임이 1시간 이내인(Rhist) 데이터 수집\n",
+ " rhistory = history.copy() # recent history\n",
+ " rhistory = rhistory[(rhistory.end_unix < present_time)]\n",
+ " hours = np.array(range(midnight, next_day + 1, 3600))\n",
+ " rhist = rhistory.copy()[rhistory.inter_no == inter_no] # 특정한 inter_no\n",
+ " rhist = rhist.reset_index(drop=True)\n",
+ " new_rows = []\n",
+ " # 1-1. 결측치 처리 : 인접한 두 end_unix의 차이가 계획된 주기의 두 배보다 크면 결측이 일어났다고 판단\n",
+ " for n in range(len(rhist) - 1):\n",
+ " curr_unix = rhist.iloc[n].end_unix # current end_unix\n",
+ " next_unix = rhist.iloc[n+1].end_unix # next end_unix\n",
+ " cycle = rhist.iloc[n].cycle\n",
+ " if next_unix - curr_unix >= 2 * cycle:\n",
+ " # 현재 unix를 계획된 주기만큼 늘려가면서 한 행씩 채워나간다.\n",
+ " #(다음 unix와의 차이가 계획된 주기보다 작거나 같아질 때까지)\n",
+ " while next_unix - curr_unix > cycle:\n",
+ " curr_unix += cycle\n",
+ " start_seconds = np.array(timetable.start_seconds)\n",
+ " idx = (start_seconds <= curr_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[idx].start_hour\n",
+ " start_minute = timetable.iloc[idx].start_minute\n",
+ " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
+ " prow = prow.drop(['start_hour', 'start_minute'], axis=1)\n",
+ " prow['end_unix'] = curr_unix\n",
+ " cycle = prow.iloc[0].cycle\n",
+ " new_rows.append(prow)\n",
+ " rhist = pd.concat([rhist] + new_rows).sort_values(['end_unix'])\n",
+ " rhist = rhist.reset_index(drop=True)\n",
+ "\n",
+ " # 1-2. 이상치 처리 : 기준유닉스로부터의 시간차이와 현시시간합이 11 이상 차이나면 이상치가 발생했다고 판단\n",
+ " Rhist = rhist.copy() # recent history 1704393231\n",
+ " Rhist = Rhist[(Rhist.end_unix >= present_time - 3600)] # Recent history (1시간 이내)\n",
+ " Rhist = Rhist.reset_index(drop=True)\n",
+ " Rhist['D_n'] = 0\n",
+ " Rhist['S_n'] = 0\n",
+ " for n in range(len(Rhist)):\n",
+ " curr_unix = Rhist.iloc[n].end_unix # current end_unix\n",
+ " cycle = Rhist.iloc[n].cycle\n",
+ " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
+ " end_unixes = rhist.end_unix.unique()\n",
+ " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
+ " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
+ " # D_n : 시간차이\n",
+ " D_n = curr_unix - base_unix\n",
+ " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " # S_n : 현시시간합\n",
+ " S_n = ddurations.values.sum() // 2\n",
+ " Rhist.loc[n, ['D_n', 'S_n']] = [D_n, S_n]\n",
+ " n = 1\n",
+ " while n < len(Rhist):\n",
+ " prev_unix = Rhist[Rhist.index==n-1]['end_unix'].iloc[0] # previous end_unix\n",
+ " curr_unix = Rhist[Rhist.index==n]['end_unix'].iloc[0] # current end_unix\n",
+ " R_n = (curr_unix - prev_unix) / cycle\n",
+ " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
+ " end_unixes = rhist.end_unix.unique()\n",
+ " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
+ " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
+ " # D_n : 시간차이\n",
+ " D_n = curr_unix - base_unix\n",
+ " # S_n : 현시시간합\n",
+ " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " S_n = ddurations.values.sum() // 2\n",
+ " # 비율이 0.5보다 작거나 같으면 해당 행을 삭제\n",
+ " if (abs(D_n - S_n) > 10) & (R_n <= 0.5):\n",
+ " Rhist = Rhist.drop(index=n)\n",
+ " n += 1\n",
+ " # 행삭제에 따른 curr_unix, D_n, S_n 등 재정의\n",
+ " if not Rhist[Rhist.index==n]['end_unix'].empty: # 마지막 행을 삭제하여 뒤의 행이 없을 때를 대비\n",
+ " curr_unix = Rhist[Rhist.index==n]['end_unix'].iloc[0] # current end_unix\n",
+ " R_n = (curr_unix - prev_unix) / cycle\n",
+ " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
+ " end_unixes = rhist.end_unix.unique()\n",
+ " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
+ " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
+ " # D_n : 시간차이\n",
+ " D_n = curr_unix - base_unix\n",
+ " # S_n : 현시시간합\n",
+ " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " S_n = ddurations.values.sum() // 2\n",
+ " # 비율이 0.5보다 크면 해당 행 조정 (비율을 유지한 채로 현시시간 대체)\n",
+ " if (abs(D_n - S_n) > 10) & (R_n > 0.5):\n",
+ " start_seconds = np.array(timetable.start_seconds)\n",
+ " idx = (start_seconds <= curr_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[idx].start_hour\n",
+ " start_minute = timetable.iloc[idx].start_minute\n",
+ " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)].copy().reset_index(drop=True).iloc[0] # planned row\n",
+ " adjusted_dur = prow[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] * R_n\n",
+ " # 조정된 현시시간을 정수로 바꿈\n",
+ " int_parts = adjusted_dur.apply(lambda x: int(x))\n",
+ " frac_parts = adjusted_dur - int_parts\n",
+ " difference = int(round(adjusted_dur.sum())) - int_parts.sum()\n",
+ " # 소수 부분이 가장 큰 상위 'difference'개의 값에 대해 올림 처리\n",
+ " for _ in range(difference):\n",
+ " max_frac_index = frac_parts.idxmax()\n",
+ " int_parts[max_frac_index] += 1\n",
+ " frac_parts[max_frac_index] = 0 # 이미 처리된 항목은 0으로 설정\n",
+ " Rhist.loc[n, [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] = int_parts.values\n",
+ " Rhist.loc[n, 'cycle'] = int_parts.sum() // 2\n",
+ " n += 1\n",
+ " Rhist = Rhist.drop(columns=['offset', 'D_n', 'S_n'])\n",
+ " Rhists.append(Rhist)\n",
+ " Rhists = pd.concat(Rhists)\n",
+ " Rhists = Rhists.sort_values(by=['end_unix', 'inter_no']).reset_index(drop=True)\n",
+ " return Rhists"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 30,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2024-01-05 08:20:00\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " end_unix | \n",
+ " dura_A1 | \n",
+ " dura_A2 | \n",
+ " dura_A3 | \n",
+ " dura_A4 | \n",
+ " dura_A5 | \n",
+ " dura_A6 | \n",
+ " dura_A7 | \n",
+ " dura_A8 | \n",
+ " dura_B1 | \n",
+ " dura_B2 | \n",
+ " dura_B3 | \n",
+ " dura_B4 | \n",
+ " dura_B5 | \n",
+ " dura_B6 | \n",
+ " dura_B7 | \n",
+ " dura_B8 | \n",
+ " cycle | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 201 | \n",
+ " 1704406820 | \n",
+ " 30 | \n",
+ " 36 | \n",
+ " 18 | \n",
+ " 58 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 30 | \n",
+ " 36 | \n",
+ " 18 | \n",
+ " 58 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 177 | \n",
+ " 1704406830 | \n",
+ " 40 | \n",
+ " 25 | \n",
+ " 71 | \n",
+ " 34 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 40 | \n",
+ " 25 | \n",
+ " 71 | \n",
+ " 34 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 170 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 210 | \n",
+ " 1704406850 | \n",
+ " 43 | \n",
+ " 39 | \n",
+ " 65 | \n",
+ " 23 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 24 | \n",
+ " 58 | \n",
+ " 65 | \n",
+ " 23 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 170 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 1704406870 | \n",
+ " 40 | \n",
+ " 42 | \n",
+ " 55 | \n",
+ " 33 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 40 | \n",
+ " 42 | \n",
+ " 29 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 170 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 176 | \n",
+ " 1704406910 | \n",
+ " 37 | \n",
+ " 93 | \n",
+ " 40 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 37 | \n",
+ " 93 | \n",
+ " 40 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 170 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 146 | \n",
+ " 175 | \n",
+ " 1704410269 | \n",
+ " 40 | \n",
+ " 42 | \n",
+ " 55 | \n",
+ " 33 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 40 | \n",
+ " 42 | \n",
+ " 29 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 170 | \n",
+ "
\n",
+ " \n",
+ " 147 | \n",
+ " 176 | \n",
+ " 1704410310 | \n",
+ " 37 | \n",
+ " 93 | \n",
+ " 40 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 37 | \n",
+ " 93 | \n",
+ " 40 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 170 | \n",
+ "
\n",
+ " \n",
+ " 148 | \n",
+ " 178 | \n",
+ " 1704410310 | \n",
+ " 38 | \n",
+ " 39 | \n",
+ " 42 | \n",
+ " 41 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 38 | \n",
+ " 39 | \n",
+ " 62 | \n",
+ " 21 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ "
\n",
+ " \n",
+ " 149 | \n",
+ " 202 | \n",
+ " 1704410320 | \n",
+ " 46 | \n",
+ " 114 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 46 | \n",
+ " 114 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ "
\n",
+ " \n",
+ " 150 | \n",
+ " 201 | \n",
+ " 1704410340 | \n",
+ " 30 | \n",
+ " 36 | \n",
+ " 18 | \n",
+ " 58 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 30 | \n",
+ " 36 | \n",
+ " 18 | \n",
+ " 58 | \n",
+ " 18 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
151 rows × 19 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no end_unix dura_A1 dura_A2 dura_A3 dura_A4 dura_A5 \\\n",
+ "0 201 1704406820 30 36 18 58 18 \n",
+ "1 177 1704406830 40 25 71 34 0 \n",
+ "2 210 1704406850 43 39 65 23 0 \n",
+ "3 175 1704406870 40 42 55 33 0 \n",
+ "4 176 1704406910 37 93 40 0 0 \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "146 175 1704410269 40 42 55 33 0 \n",
+ "147 176 1704410310 37 93 40 0 0 \n",
+ "148 178 1704410310 38 39 42 41 0 \n",
+ "149 202 1704410320 46 114 0 0 0 \n",
+ "150 201 1704410340 30 36 18 58 18 \n",
+ "\n",
+ " dura_A6 dura_A7 dura_A8 dura_B1 dura_B2 dura_B3 dura_B4 dura_B5 \\\n",
+ "0 0 0 0 30 36 18 58 18 \n",
+ "1 0 0 0 40 25 71 34 0 \n",
+ "2 0 0 0 24 58 65 23 0 \n",
+ "3 0 0 0 40 42 29 59 0 \n",
+ "4 0 0 0 37 93 40 0 0 \n",
+ ".. ... ... ... ... ... ... ... ... \n",
+ "146 0 0 0 40 42 29 59 0 \n",
+ "147 0 0 0 37 93 40 0 0 \n",
+ "148 0 0 0 38 39 62 21 0 \n",
+ "149 0 0 0 46 114 0 0 0 \n",
+ "150 0 0 0 30 36 18 58 18 \n",
+ "\n",
+ " dura_B6 dura_B7 dura_B8 cycle \n",
+ "0 0 0 0 160 \n",
+ "1 0 0 0 170 \n",
+ "2 0 0 0 170 \n",
+ "3 0 0 0 170 \n",
+ "4 0 0 0 170 \n",
+ ".. ... ... ... ... \n",
+ "146 0 0 0 170 \n",
+ "147 0 0 0 170 \n",
+ "148 0 0 0 160 \n",
+ "149 0 0 0 160 \n",
+ "150 0 0 0 160 \n",
+ "\n",
+ "[151 rows x 19 columns]"
+ ]
+ },
+ "execution_count": 30,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "Rhists = make_rhistory(100)\n",
+ "Rhists"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_histid(m):\n",
+ " fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
+ " present_time = fmins[m]\n",
+ " rhistory = make_rhistory(m)\n",
+ " # 2. 시작 유닉스 타임컬럼 생성 후 종류 유닉스 타임에서 현시별 현시기간 컬럼의 합을 뺀 값으로 입력\n",
+ " # - 현시시간의 합을 뺀 시간의 +- 10초 이내에 이전 주기정보가 존재하면 그 유닉스 시간을 시작 유닉스시간 값으로 하고, 존재하지 않으면 현시시간의 합을 뺀 유닉스 시간을 시작 유닉스 시간으로 지정\n",
+ " for i, row in rhistory.iterrows():\n",
+ " # 이전 유닉스 존재하지 않음 => 현시시간 합의 차\n",
+ " # 이전 유닉스 존재, abs < 10 => 이전 유닉스\n",
+ " # 이전 유닉스 존재, abs >=10 => 현시시간 합의 차\n",
+ " inter_no = row.inter_no\n",
+ " end_unix = row.end_unix\n",
+ " elapsed_time = row[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]].sum() // 2 # 현시시간 합\n",
+ " start_unix = end_unix - elapsed_time\n",
+ " pre_rows = history[:i] # previous rows\n",
+ " if inter_no in pre_rows.inter_no.unique(): # 이전 유닉스 존재\n",
+ " pre_unix = pre_rows[pre_rows.inter_no == inter_no]['end_unix'].iloc[-1] # previous unix time\n",
+ " if abs(pre_unix - start_unix) < 10: # abs < 10\n",
+ " start_unix = pre_unix\n",
+ " else: # abs >= 10\n",
+ " pass\n",
+ " rhistory.loc[i, 'start_unix'] = start_unix\n",
+ " rhistory[rhistory.isna()] = 0\n",
+ " rhistory['start_unix'] = rhistory['start_unix'].astype(int)\n",
+ " # # with pd.option_context('display.max_rows', None, 'display.max_columns', None):\n",
+ " # # display(rhistory)\n",
+ " rhistory = rhistory[['inter_no', 'start_unix'] + [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)] + ['cycle']]\n",
+ "\n",
+ " # 계층화된 형태로 변환\n",
+ " hrhistory = [] # hierarchied recent history\n",
+ " for i, row in rhistory.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_unix = row.start_unix\n",
+ "\n",
+ " ind = (timetable['start_seconds'] <= row.start_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[ind].start_hour\n",
+ " start_minute = timetable.iloc[ind].start_minute\n",
+ " isplit = isplits[(inter_no, start_hour, start_minute)]\n",
+ " phas_As = [isplit[j][0] for j in isplit.keys()]\n",
+ " phas_Bs = [isplit[j][1] for j in isplit.keys()]\n",
+ " durs_A = row[[f'dura_A{j}' for j in range(1,9)]]\n",
+ " durs_B = row[[f'dura_B{j}' for j in range(1,9)]]\n",
+ " durations = []\n",
+ " for j in range(1, len(isplit)+1):\n",
+ " ja = isplit[j][0]\n",
+ " jb = isplit[j][1]\n",
+ " if ja == jb:\n",
+ " durations.append(min(durs_A[ja-1], durs_B[jb-1]))\n",
+ " else:\n",
+ " durations.append(abs(durs_A[ja-1] - durs_B[ja-1]))\n",
+ " new_rows = pd.DataFrame({'inter_no':[inter_no] * len(durations), 'start_unix':[start_unix] * len(durations),\n",
+ " 'phas_A':phas_As, 'phas_B':phas_Bs, 'duration':durations})\n",
+ " hrhistory.append(new_rows)\n",
+ " hrhistory = pd.concat(hrhistory)\n",
+ " hrhistory = hrhistory.sort_values(by = ['start_unix', 'inter_no', 'phas_A', 'phas_B']).reset_index(drop=True)\n",
+ "\n",
+ " # 5초단위로 수집한 이동류정보(time2movement[present_time])와 최근 1시간 신호이력(hrhistory)을 병합\n",
+ " movedur = pd.merge(time2movement[present_time], hrhistory, how='inner', on=['inter_no', 'start_unix', 'phas_A', 'phas_B']) # movements and durations\n",
+ " movedur = movedur.sort_values(by=['start_unix', 'inter_no', 'phas_A','phas_B'])\n",
+ " movedur = movedur[['inter_no', 'start_unix', 'phas_A', 'phas_B', 'move_A', 'move_B', 'duration']]\n",
+ "\n",
+ " # 이동류 매칭 테이블에서 진입id, 진출id를 가져와서 붙임.\n",
+ " for i, row in movedur.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_unix = row.start_unix\n",
+ " # incoming and outgoing edges A\n",
+ " move_A = row.move_A\n",
+ " if move_A in [17, 18]:\n",
+ " inc_edge_A = np.nan\n",
+ " out_edge_A = np.nan\n",
+ " else:\n",
+ " match_A = matching[(matching.inter_no == inter_no) & (matching.move_no == move_A)].iloc[0]\n",
+ " inc_edge_A = match_A.inc_edge\n",
+ " out_edge_A = match_A.out_edge\n",
+ " movedur.loc[i, ['inc_edge_A', 'out_edge_A']] = [inc_edge_A, out_edge_A]\n",
+ " # incoming and outgoing edges B\n",
+ " move_B = row.move_B\n",
+ " if move_B in [17, 18]:\n",
+ " inc_edge_B = np.nan\n",
+ " out_edge_B = np.nan\n",
+ " else:\n",
+ " match_B = matching[(matching.inter_no == inter_no) & (matching.move_no == move_B)].iloc[0]\n",
+ " inc_edge_B = match_B.inc_edge\n",
+ " out_edge_B = match_B.out_edge\n",
+ " movedur.loc[i, ['inc_edge_B', 'out_edge_B']] = [inc_edge_B, out_edge_B]\n",
+ "\n",
+ " # 이동류 컬럼 제거\n",
+ " movedur = movedur.drop(['move_A', 'move_B'], axis=1)\n",
+ "\n",
+ " histid = movedur.copy() # history with edge ids (incoming and outgoing edge ids)\n",
+ " histid['node_id'] = histid['inter_no'].map(inter2node)\n",
+ " histid = histid[['inter_no', 'node_id', 'start_unix', 'phas_A', 'phas_B', 'duration', 'inc_edge_A', 'out_edge_A', 'inc_edge_B', 'out_edge_B']]\n",
+ " histid = histid[histid.start_unix > present_time - 3600]\n",
+ " # 시뮬레이션 시작시각 : 현재시각 - 600\n",
+ " # 시뮬레이션 종료시각 : 현재시각 - 300\n",
+ " # 현재시각 : present_time, PT\n",
+ " # PT-900 ... PT-600 ... PT-300 ... PT\n",
+ " return histid"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "m = 120\n",
+ "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
+ "present_time = fmins[m]\n",
+ "rhistory = make_rhistory(m)\n",
+ "# 2. 시작 유닉스 타임컬럼 생성 후 종류 유닉스 타임에서 현시별 현시기간 컬럼의 합을 뺀 값으로 입력\n",
+ "# - 현시시간의 합을 뺀 시간의 +- 10초 이내에 이전 주기정보가 존재하면 그 유닉스 시간을 시작 유닉스시간 값으로 하고, 존재하지 않으면 현시시간의 합을 뺀 유닉스 시간을 시작 유닉스 시간으로 지정\n",
+ "for i, row in rhistory.iterrows():\n",
+ " # 이전 유닉스 존재하지 않음 => 현시시간 합의 차\n",
+ " # 이전 유닉스 존재, abs < 10 => 이전 유닉스\n",
+ " # 이전 유닉스 존재, abs >=10 => 현시시간 합의 차\n",
+ " inter_no = row.inter_no\n",
+ " end_unix = row.end_unix\n",
+ " elapsed_time = row[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]].sum() // 2 # 현시시간 합\n",
+ " start_unix = end_unix - elapsed_time\n",
+ " pre_rows = history[:i] # previous rows\n",
+ " if inter_no in pre_rows.inter_no.unique(): # 이전 유닉스 존재\n",
+ " pre_unix = pre_rows[pre_rows.inter_no == inter_no]['end_unix'].iloc[-1] # previous unix time\n",
+ " if abs(pre_unix - start_unix) < 10: # abs < 10\n",
+ " start_unix = pre_unix\n",
+ " else: # abs >= 10\n",
+ " pass\n",
+ " rhistory.loc[i, 'start_unix'] = start_unix\n",
+ "rhistory[rhistory.isna()] = 0\n",
+ "rhistory['start_unix'] = rhistory['start_unix'].astype(int)\n",
+ "# # with pd.option_context('display.max_rows', None, 'display.max_columns', None):\n",
+ "# # display(rhistory)\n",
+ "rhistory = rhistory[['inter_no', 'start_unix'] + [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)] + ['cycle']]\n",
+ "\n",
+ "# rhistoryy = rhistory.copy()[rhistory.inter_no==175]\n",
+ "# rhistoryy['diff'] = rhistoryy['start_unix'].diff()\n",
+ "\n",
+ "# 계층화된 형태로 변환\n",
+ "hrhistory = [] # hierarchied recent history\n",
+ "for i, row in rhistory.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_unix = row.start_unix\n",
+ "\n",
+ " ind = (timetable['start_seconds'] <= row.start_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[ind].start_hour\n",
+ " start_minute = timetable.iloc[ind].start_minute\n",
+ " isplit = isplits[(inter_no, start_hour, start_minute)]\n",
+ " phas_As = [isplit[j][0] for j in isplit.keys()]\n",
+ " phas_Bs = [isplit[j][1] for j in isplit.keys()]\n",
+ " durs_A = row[[f'dura_A{j}' for j in range(1,9)]]\n",
+ " durs_B = row[[f'dura_B{j}' for j in range(1,9)]]\n",
+ " durations = []\n",
+ " for j in range(1, len(isplit)+1):\n",
+ " ja = isplit[j][0]\n",
+ " jb = isplit[j][1]\n",
+ " if ja == jb:\n",
+ " durations.append(min(durs_A[ja-1], durs_B[jb-1]))\n",
+ " else:\n",
+ " durations.append(abs(durs_A[ja-1] - durs_B[ja-1]))\n",
+ " new_rows = pd.DataFrame({'inter_no':[inter_no] * len(durations), 'start_unix':[start_unix] * len(durations),\n",
+ " 'phas_A':phas_As, 'phas_B':phas_Bs, 'duration':durations})\n",
+ " hrhistory.append(new_rows)\n",
+ "hrhistory = pd.concat(hrhistory)\n",
+ "hrhistory = hrhistory.sort_values(by = ['start_unix', 'inter_no', 'phas_A', 'phas_B']).reset_index(drop=True)\n",
+ "\n",
+ "hrhistoryy = rhistory.copy()[rhistory.inter_no==175]\n",
+ "hrhistoryy['diff'] = hrhistoryy['start_unix'].diff()\n",
+ "\n",
+ "# display(hrhistoryy[:60])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for inter_no in sorted(plan.inter_no.unique()):\n",
+ " print(inter_no)\n",
+ " movement = time2movement[present_time]\n",
+ " movementt = movement.copy()[movement.inter_no==inter_no]\n",
+ " hrhistoryy = rhistory.copy()[rhistory.inter_no==inter_no]\n",
+ " mdts = sorted(movementt.start_unix.unique())\n",
+ " hdts = sorted(hrhistoryy.start_unix.unique())\n",
+ " import matplotlib.pyplot as plt\n",
+ " plt.scatter(mdts, [0]*len(mdts), c='b')\n",
+ " plt.scatter(hdts, [1]*len(hdts), c='r')\n",
+ " plt.show()\n",
+ " # display(movementt)\n",
+ " # display(hrhistoryy)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 5초단위로 수집한 이동류정보(time2movement[present_time])와 최근 1시간 신호이력(hrhistory)을 병합\n",
+ "movedur = pd.merge(time2movement[present_time], hrhistory, how='inner', on=['inter_no', 'start_unix', 'phas_A', 'phas_B']) # movements and durations\n",
+ "movedur = movedur.sort_values(by=['start_unix', 'inter_no', 'phas_A','phas_B'])\n",
+ "movedur = movedur[['inter_no', 'start_unix', 'phas_A', 'phas_B', 'move_A', 'move_B', 'duration']]\n",
+ "\n",
+ "# 이동류 매칭 테이블에서 진입id, 진출id를 가져와서 붙임.\n",
+ "for i, row in movedur.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_unix = row.start_unix\n",
+ " # incoming and outgoing edges A\n",
+ " move_A = row.move_A\n",
+ " if move_A in [17, 18]:\n",
+ " inc_edge_A = np.nan\n",
+ " out_edge_A = np.nan\n",
+ " else:\n",
+ " match_A = matching[(matching.inter_no == inter_no) & (matching.move_no == move_A)].iloc[0]\n",
+ " inc_edge_A = match_A.inc_edge\n",
+ " out_edge_A = match_A.out_edge\n",
+ " movedur.loc[i, ['inc_edge_A', 'out_edge_A']] = [inc_edge_A, out_edge_A]\n",
+ " # incoming and outgoing edges B\n",
+ " move_B = row.move_B\n",
+ " if move_B in [17, 18]:\n",
+ " inc_edge_B = np.nan\n",
+ " out_edge_B = np.nan\n",
+ " else:\n",
+ " match_B = matching[(matching.inter_no == inter_no) & (matching.move_no == move_B)].iloc[0]\n",
+ " inc_edge_B = match_B.inc_edge\n",
+ " out_edge_B = match_B.out_edge\n",
+ " movedur.loc[i, ['inc_edge_B', 'out_edge_B']] = [inc_edge_B, out_edge_B]\n",
+ "\n",
+ "# 이동류 컬럼 제거\n",
+ "movedur = movedur.drop(['move_A', 'move_B'], axis=1)\n",
+ "\n",
+ "histid = movedur.copy() # history with edge ids (incoming and outgoing edge ids)\n",
+ "histid['node_id'] = histid['inter_no'].map(inter2node)\n",
+ "histid = histid[['inter_no', 'node_id', 'start_unix', 'phas_A', 'phas_B', 'duration', 'inc_edge_A', 'out_edge_A', 'inc_edge_B', 'out_edge_B']]\n",
+ "histid = histid[histid.start_unix > present_time - 3600]\n",
+ "# 시뮬레이션 시작시각 : 현재시각 - 600\n",
+ "# 시뮬레이션 종료시각 : 현재시각 - 300\n",
+ "# 현재시각 : present_time, PT\n",
+ "# PT-900 ... PT-600 ... PT-300 ... PT\n",
+ "\n",
+ "histidd = histid.copy()[histid.inter_no==175]\n",
+ "histidd['diff'] = histidd['start_unix'].diff()\n",
+ "histidd[:60]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2024-01-05 08:20:00\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " node_id | \n",
+ " start_unix | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " duration | \n",
+ " inc_edge_A | \n",
+ " out_edge_A | \n",
+ " inc_edge_B | \n",
+ " out_edge_B | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704406830 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 40 | \n",
+ " -571542809_01 | \n",
+ " 571542811_01 | \n",
+ " 571542811_02 | \n",
+ " 571542809_01 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704406830 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 25 | \n",
+ " 571542811_02 | \n",
+ " 571542107_01 | \n",
+ " -571542809_01 | \n",
+ " 571542809_01 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704406830 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 71 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704406830 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 34 | \n",
+ " -571542809_01 | \n",
+ " 571542811_01 | \n",
+ " 571542107_02 | \n",
+ " 571542809_01 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704406870 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 40 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704406870 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 42 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704406870 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 29 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704406870 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 26 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 8 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704406870 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 33 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 9 | \n",
+ " 176 | \n",
+ " i1 | \n",
+ " 1704406910 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542810_01 | \n",
+ " -571542797_02.99 | \n",
+ " 571542797_02.99 | \n",
+ " 571542810_01 | \n",
+ "
\n",
+ " \n",
+ " 10 | \n",
+ " 176 | \n",
+ " i1 | \n",
+ " 1704406910 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 93 | \n",
+ " -571542810_01 | \n",
+ " -571542797_02.99 | \n",
+ " -571542810_01 | \n",
+ " 571543469_01 | \n",
+ "
\n",
+ " \n",
+ " 11 | \n",
+ " 176 | \n",
+ " i1 | \n",
+ " 1704406910 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 40 | \n",
+ " 571543469_02 | \n",
+ " -571542797_02.99 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 12 | \n",
+ " 178 | \n",
+ " i3 | \n",
+ " 1704406950 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 38 | \n",
+ " 571540304_02 | \n",
+ " 571556450_01 | \n",
+ " 571556450_02 | \n",
+ " 571540304_01 | \n",
+ "
\n",
+ " \n",
+ " 13 | \n",
+ " 178 | \n",
+ " i3 | \n",
+ " 1704406950 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " 571556450_02 | \n",
+ " 571500475_01 | \n",
+ " 571540304_02 | \n",
+ " 571540303_01 | \n",
+ "
\n",
+ " \n",
+ " 14 | \n",
+ " 178 | \n",
+ " i3 | \n",
+ " 1704406950 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 42 | \n",
+ " 571540303_02.21 | \n",
+ " 571556450_01 | \n",
+ " 571540303_02.21 | \n",
+ " 571500475_01 | \n",
+ "
\n",
+ " \n",
+ " 15 | \n",
+ " 178 | \n",
+ " i3 | \n",
+ " 1704406950 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 21 | \n",
+ " -571500475_01 | \n",
+ " 571540303_01 | \n",
+ " -571500475_01 | \n",
+ " 571540304_01 | \n",
+ "
\n",
+ " \n",
+ " 16 | \n",
+ " 202 | \n",
+ " i9 | \n",
+ " 1704406950 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 46 | \n",
+ " 571510152_02 | \n",
+ " -571510152_01 | \n",
+ " 571510152_01 | \n",
+ " 571510152_01.65 | \n",
+ "
\n",
+ " \n",
+ " 17 | \n",
+ " 202 | \n",
+ " i9 | \n",
+ " 1704406950 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 114 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 18 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704407000 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 40 | \n",
+ " -571542809_01 | \n",
+ " 571542811_01 | \n",
+ " 571542811_02 | \n",
+ " 571542809_01 | \n",
+ "
\n",
+ " \n",
+ " 19 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704407000 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 25 | \n",
+ " 571542811_02 | \n",
+ " 571542107_01 | \n",
+ " -571542809_01 | \n",
+ " 571542809_01 | \n",
+ "
\n",
+ " \n",
+ " 20 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704407000 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 71 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 21 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704407000 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 34 | \n",
+ " -571542809_01 | \n",
+ " 571542811_01 | \n",
+ " 571542107_02 | \n",
+ " 571542809_01 | \n",
+ "
\n",
+ " \n",
+ " 22 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704407040 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 40 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 23 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704407040 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 42 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 24 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704407040 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 29 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 25 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704407040 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 26 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 26 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704407040 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 33 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 27 | \n",
+ " 176 | \n",
+ " i1 | \n",
+ " 1704407080 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542810_01 | \n",
+ " -571542797_02.99 | \n",
+ " 571542797_02.99 | \n",
+ " 571542810_01 | \n",
+ "
\n",
+ " \n",
+ " 28 | \n",
+ " 176 | \n",
+ " i1 | \n",
+ " 1704407080 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 93 | \n",
+ " -571542810_01 | \n",
+ " -571542797_02.99 | \n",
+ " -571542810_01 | \n",
+ " 571543469_01 | \n",
+ "
\n",
+ " \n",
+ " 29 | \n",
+ " 176 | \n",
+ " i1 | \n",
+ " 1704407080 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 40 | \n",
+ " 571543469_02 | \n",
+ " -571542797_02.99 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no node_id start_unix phas_A phas_B duration inc_edge_A \\\n",
+ "0 177 i2 1704406830 1 1 40 -571542809_01 \n",
+ "1 177 i2 1704406830 2 2 25 571542811_02 \n",
+ "2 177 i2 1704406830 3 3 71 NaN \n",
+ "3 177 i2 1704406830 4 4 34 -571542809_01 \n",
+ "4 175 i0 1704406870 1 1 40 -571542797_02 \n",
+ "5 175 i0 1704406870 2 2 42 -571500487_01 \n",
+ "6 175 i0 1704406870 3 3 29 571545870_02 \n",
+ "7 175 i0 1704406870 3 4 26 571545870_02 \n",
+ "8 175 i0 1704406870 4 4 33 571510153_02 \n",
+ "9 176 i1 1704406910 1 1 37 -571542810_01 \n",
+ "10 176 i1 1704406910 2 2 93 -571542810_01 \n",
+ "11 176 i1 1704406910 3 3 40 571543469_02 \n",
+ "12 178 i3 1704406950 1 1 38 571540304_02 \n",
+ "13 178 i3 1704406950 2 2 39 571556450_02 \n",
+ "14 178 i3 1704406950 3 3 42 571540303_02.21 \n",
+ "15 178 i3 1704406950 4 4 21 -571500475_01 \n",
+ "16 202 i9 1704406950 1 1 46 571510152_02 \n",
+ "17 202 i9 1704406950 2 2 114 NaN \n",
+ "18 177 i2 1704407000 1 1 40 -571542809_01 \n",
+ "19 177 i2 1704407000 2 2 25 571542811_02 \n",
+ "20 177 i2 1704407000 3 3 71 NaN \n",
+ "21 177 i2 1704407000 4 4 34 -571542809_01 \n",
+ "22 175 i0 1704407040 1 1 40 -571542797_02 \n",
+ "23 175 i0 1704407040 2 2 42 -571500487_01 \n",
+ "24 175 i0 1704407040 3 3 29 571545870_02 \n",
+ "25 175 i0 1704407040 3 4 26 571545870_02 \n",
+ "26 175 i0 1704407040 4 4 33 571510153_02 \n",
+ "27 176 i1 1704407080 1 1 37 -571542810_01 \n",
+ "28 176 i1 1704407080 2 2 93 -571542810_01 \n",
+ "29 176 i1 1704407080 3 3 40 571543469_02 \n",
+ "\n",
+ " out_edge_A inc_edge_B out_edge_B \n",
+ "0 571542811_01 571542811_02 571542809_01 \n",
+ "1 571542107_01 -571542809_01 571542809_01 \n",
+ "2 NaN NaN NaN \n",
+ "3 571542811_01 571542107_02 571542809_01 \n",
+ "4 571500487_01 -571500487_01 571542797_02 \n",
+ "5 571545870_01 -571542797_02 571510153_01 \n",
+ "6 571510153_01 571545870_02 571542797_02 \n",
+ "7 571510153_01 571510153_02 571545870_01 \n",
+ "8 571500487_01 571510153_02 571545870_01 \n",
+ "9 -571542797_02.99 571542797_02.99 571542810_01 \n",
+ "10 -571542797_02.99 -571542810_01 571543469_01 \n",
+ "11 -571542797_02.99 NaN NaN \n",
+ "12 571556450_01 571556450_02 571540304_01 \n",
+ "13 571500475_01 571540304_02 571540303_01 \n",
+ "14 571556450_01 571540303_02.21 571500475_01 \n",
+ "15 571540303_01 -571500475_01 571540304_01 \n",
+ "16 -571510152_01 571510152_01 571510152_01.65 \n",
+ "17 NaN NaN NaN \n",
+ "18 571542811_01 571542811_02 571542809_01 \n",
+ "19 571542107_01 -571542809_01 571542809_01 \n",
+ "20 NaN NaN NaN \n",
+ "21 571542811_01 571542107_02 571542809_01 \n",
+ "22 571500487_01 -571500487_01 571542797_02 \n",
+ "23 571545870_01 -571542797_02 571510153_01 \n",
+ "24 571510153_01 571545870_02 571542797_02 \n",
+ "25 571510153_01 571510153_02 571545870_01 \n",
+ "26 571500487_01 571510153_02 571545870_01 \n",
+ "27 -571542797_02.99 571542797_02.99 571542810_01 \n",
+ "28 -571542797_02.99 -571542810_01 571543469_01 \n",
+ "29 -571542797_02.99 NaN NaN "
+ ]
+ },
+ "execution_count": 18,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "make_histid(100)[:30]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "inter_no = 175\n",
+ "rhist = make_histid(100)\n",
+ "rhis = rhist.copy()[rhist.inter_no==inter_no]\n",
+ "rhis['diff'] = rhis['start_unix'].diff()\n",
+ "rhis[:60]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "inter_no = 175\n",
+ "histid = make_histid(100)\n",
+ "his = histid.copy()[histid.inter_no==inter_no]\n",
+ "his['diff'] = his['start_unix'].diff()\n",
+ "his[:60]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for m in range(30, 288):\n",
+ " print(m)\n",
+ " make_histid(m).to_csv(f'../../Data/tables/histids/histids_{fmins[m]}.csv')"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "rts",
+ "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.8.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/Analysis/0109_preprocess/0122_preprocess_9.6.ipynb b/Analysis/0109_preprocess/0122_preprocess_9.6.ipynb
new file mode 100644
index 000000000..0294b6f09
--- /dev/null
+++ b/Analysis/0109_preprocess/0122_preprocess_9.6.ipynb
@@ -0,0 +1,7526 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import os\n",
+ "import sumolib\n",
+ "import random\n",
+ "from tqdm import tqdm\n",
+ "from datetime import datetime"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# A. 이동류 매칭"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "100%|██████████| 17281/17281 [00:13<00:00, 1257.14it/s]\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " move_A | \n",
+ " move_B | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 7 | \n",
+ " 3 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 6 | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 6 | \n",
+ " 2 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 5 | \n",
+ " 2 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 176 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 8 | \n",
+ " 3 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 176 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 5 | \n",
+ " 18 | \n",
+ "
\n",
+ " \n",
+ " 8 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ " 9 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 7 | \n",
+ " 3 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phas_A phas_B move_A move_B\n",
+ "0 175 1 1 8 4\n",
+ "1 175 2 2 7 3\n",
+ "2 175 3 3 6 1\n",
+ "3 175 3 4 6 2\n",
+ "4 175 4 4 5 2\n",
+ "5 176 1 1 8 4\n",
+ "6 176 2 2 8 3\n",
+ "7 176 3 3 5 18\n",
+ "8 177 1 1 8 4\n",
+ "9 177 2 2 7 3"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# [이동류번호] 불러오기 (약 1분의 소요시간)\n",
+ "path_moves = '../../Data/tables/moves/'\n",
+ "csv_moves = os.listdir('../../Data/tables/moves/')\n",
+ "moves = [pd.read_csv(path_moves + csv_move, index_col=0) for csv_move in tqdm(csv_moves)]\n",
+ "match1 = pd.concat(moves).drop_duplicates().sort_values(by=['inter_no','phas_A','phas_B']).reset_index(drop=True)\n",
+ "match1.head(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ "
\n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 2 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no\n",
+ "0 175 1 A 8\n",
+ "0 175 1 B 4\n",
+ "1 175 2 A 7\n",
+ "1 175 2 B 3\n",
+ "2 175 3 A 6\n",
+ "2 175 3 B 1\n",
+ "4 175 4 A 5\n",
+ "3 175 4 B 2\n",
+ "5 176 1 A 8\n",
+ "5 176 1 B 4"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# 계층화 (inter_no, phas_A, phas_B, move_A, move_B) -> ('inter_no', 'phase_no', 'ring_type', 'move_no')\n",
+ "matchA = match1[['inter_no', 'phas_A', 'move_A']].copy()\n",
+ "matchA.columns = ['inter_no', 'phase_no', 'move_no']\n",
+ "matchA['ring_type'] = 'A'\n",
+ "matchB = match1[['inter_no', 'phas_B', 'move_B']].copy()\n",
+ "matchB.columns = ['inter_no', 'phase_no', 'move_no']\n",
+ "matchB['ring_type'] = 'B'\n",
+ "match2 = pd.concat([matchA, matchB]).drop_duplicates()\n",
+ "match2 = match2[['inter_no', 'phase_no', 'ring_type', 'move_no']]\n",
+ "match2 = match2.sort_values(by=list(match2.columns))\n",
+ "match2.head(10)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 45,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 8 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 9 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 10 | \n",
+ " 176 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 11 | \n",
+ " 176 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 12 | \n",
+ " 176 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 13 | \n",
+ " 176 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 14 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 15 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 16 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 17 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 18 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 19 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 20 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 21 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 22 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 23 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 24 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 25 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 26 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 27 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 28 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 29 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 30 | \n",
+ " 201 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 31 | \n",
+ " 201 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 32 | \n",
+ " 201 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 33 | \n",
+ " 201 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 34 | \n",
+ " 201 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 35 | \n",
+ " 201 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 36 | \n",
+ " 201 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 37 | \n",
+ " 201 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 38 | \n",
+ " 201 | \n",
+ " 5 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 39 | \n",
+ " 201 | \n",
+ " 5 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 40 | \n",
+ " 202 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 41 | \n",
+ " 202 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 42 | \n",
+ " 202 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 43 | \n",
+ " 202 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 44 | \n",
+ " 206 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 45 | \n",
+ " 206 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 46 | \n",
+ " 206 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 47 | \n",
+ " 206 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 48 | \n",
+ " 206 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 49 | \n",
+ " 206 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 50 | \n",
+ " 206 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 51 | \n",
+ " 206 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 52 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ " 53 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 54 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 55 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 56 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ "
\n",
+ " \n",
+ " 57 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ "
\n",
+ " \n",
+ " 58 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ "
\n",
+ " \n",
+ " 59 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir\n",
+ "0 175 1 A 8 남 북\n",
+ "1 175 1 B 4 북 남\n",
+ "2 175 2 A 7 북 동\n",
+ "3 175 2 B 3 남 서\n",
+ "4 175 3 A 6 동 서\n",
+ "5 175 3 B 1 동 남\n",
+ "6 175 4 A 5 서 북\n",
+ "7 175 4 B 2 서 동\n",
+ "8 176 1 A 8 남 북\n",
+ "9 176 1 B 4 북 남\n",
+ "10 176 2 A 8 남 북\n",
+ "11 176 2 B 3 남 서\n",
+ "12 176 3 A 5 서 북\n",
+ "13 176 3 B 18 NaN NaN\n",
+ "14 177 1 A 8 남 북\n",
+ "15 177 1 B 4 북 남\n",
+ "16 177 2 A 7 북 동\n",
+ "17 177 2 B 3 남 서\n",
+ "18 177 3 A 17 NaN NaN\n",
+ "19 177 3 B 18 NaN NaN\n",
+ "20 177 4 A 5 서 북\n",
+ "21 177 4 B 1 동 남\n",
+ "22 178 1 A 8 남 북\n",
+ "23 178 1 B 4 북 남\n",
+ "24 178 2 A 7 북 동\n",
+ "25 178 2 B 3 남 서\n",
+ "26 178 3 A 5 서 북\n",
+ "27 178 3 B 2 서 동\n",
+ "28 178 4 A 6 동 서\n",
+ "29 178 4 B 1 동 남\n",
+ "30 201 1 A 8 남 북\n",
+ "31 201 1 B 3 남 서\n",
+ "32 201 2 A 5 서 북\n",
+ "33 201 2 B 2 서 동\n",
+ "34 201 3 A 6 동 서\n",
+ "35 201 3 B 2 서 동\n",
+ "36 201 4 A 6 동 서\n",
+ "37 201 4 B 1 동 남\n",
+ "38 201 5 A 7 북 동\n",
+ "39 201 5 B 4 북 남\n",
+ "40 202 1 A 6 동 서\n",
+ "41 202 1 B 2 서 동\n",
+ "42 202 2 A 17 NaN NaN\n",
+ "43 202 2 B 18 NaN NaN\n",
+ "44 206 1 A 8 남 북\n",
+ "45 206 1 B 4 북 남\n",
+ "46 206 2 A 17 NaN NaN\n",
+ "47 206 2 B 18 NaN NaN\n",
+ "48 206 3 A 8 남 북\n",
+ "49 206 3 B 4 북 남\n",
+ "50 206 4 A 17 NaN NaN\n",
+ "51 206 4 B 18 NaN NaN\n",
+ "52 210 1 A 6 동 서\n",
+ "53 210 1 B 18 NaN NaN\n",
+ "54 210 2 A 5 서 북\n",
+ "55 210 2 B 2 서 동\n",
+ "56 210 3 A 7 북 동\n",
+ "57 210 3 B 4 북 남\n",
+ "58 210 4 A 8 남 북\n",
+ "59 210 4 B 3 남 서"
+ ]
+ },
+ "execution_count": 45,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# [nema 이동류목록] 불러오기 및 병합\n",
+ "nema = pd.read_csv('../../Data/tables/nema.csv', encoding='cp949')\n",
+ "match3 = pd.merge(match2, nema, how='left', on='move_no').drop_duplicates()\n",
+ "match3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 46,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 179 | \n",
+ " 004 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 003 | \n",
+ " 176 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 001 | \n",
+ " 095 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 179 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 8 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 9 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 359 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 10 | \n",
+ " 176 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 11 | \n",
+ " 176 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 12 | \n",
+ " 176 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 356 | \n",
+ "
\n",
+ " \n",
+ " 13 | \n",
+ " 176 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 14 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 15 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 001 | \n",
+ " 176 | \n",
+ "
\n",
+ " \n",
+ " 16 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 17 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 179 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 18 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 19 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 20 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 21 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 22 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 23 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 24 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 25 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 26 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 27 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 28 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 29 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 30 | \n",
+ " 201 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 31 | \n",
+ " 201 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 32 | \n",
+ " 201 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 33 | \n",
+ " 201 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 34 | \n",
+ " 201 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 35 | \n",
+ " 201 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 36 | \n",
+ " 201 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 37 | \n",
+ " 201 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 38 | \n",
+ " 201 | \n",
+ " 5 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 39 | \n",
+ " 201 | \n",
+ " 5 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 40 | \n",
+ " 202 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 41 | \n",
+ " 202 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 42 | \n",
+ " 202 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 43 | \n",
+ " 202 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 44 | \n",
+ " 206 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 45 | \n",
+ " 206 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 46 | \n",
+ " 206 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 47 | \n",
+ " 206 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 48 | \n",
+ " 206 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 49 | \n",
+ " 206 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 50 | \n",
+ " 206 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 51 | \n",
+ " 206 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 52 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ " 53 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 54 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 55 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 56 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 359 | \n",
+ " 090 | \n",
+ "
\n",
+ " \n",
+ " 57 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ "
\n",
+ " \n",
+ " 58 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ "
\n",
+ " \n",
+ " 59 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle\n",
+ "0 175 1 A 8 남 북 179 004\n",
+ "1 175 1 B 4 북 남 003 176\n",
+ "2 175 2 A 7 북 동 001 095\n",
+ "3 175 2 B 3 남 서 179 270\n",
+ "4 175 3 A 6 동 서 090 270\n",
+ "5 175 3 B 1 동 남 090 180\n",
+ "6 175 4 A 5 서 북 268 000\n",
+ "7 175 4 B 2 서 동 270 090\n",
+ "8 176 1 A 8 남 북 180 000\n",
+ "9 176 1 B 4 북 남 359 180\n",
+ "10 176 2 A 8 남 북 180 000\n",
+ "11 176 2 B 3 남 서 180 270\n",
+ "12 176 3 A 5 서 북 270 356\n",
+ "13 176 3 B 18 NaN NaN NaN NaN\n",
+ "14 177 1 A 8 남 북 180 000\n",
+ "15 177 1 B 4 북 남 001 176\n",
+ "16 177 2 A 7 북 동 000 090\n",
+ "17 177 2 B 3 남 서 179 270\n",
+ "18 177 3 A 17 NaN NaN NaN NaN\n",
+ "19 177 3 B 18 NaN NaN NaN NaN\n",
+ "20 177 4 A 5 서 북 268 000\n",
+ "21 177 4 B 1 동 남 090 180\n",
+ "22 178 1 A 8 남 북 180 000\n",
+ "23 178 1 B 4 북 남 000 180\n",
+ "24 178 2 A 7 북 동 000 090\n",
+ "25 178 2 B 3 남 서 180 270\n",
+ "26 178 3 A 5 서 북 270 000\n",
+ "27 178 3 B 2 서 동 270 090\n",
+ "28 178 4 A 6 동 서 090 270\n",
+ "29 178 4 B 1 동 남 090 180\n",
+ "30 201 1 A 8 남 북 180 000\n",
+ "31 201 1 B 3 남 서 180 270\n",
+ "32 201 2 A 5 서 북 270 000\n",
+ "33 201 2 B 2 서 동 270 090\n",
+ "34 201 3 A 6 동 서 090 270\n",
+ "35 201 3 B 2 서 동 270 090\n",
+ "36 201 4 A 6 동 서 090 270\n",
+ "37 201 4 B 1 동 남 090 180\n",
+ "38 201 5 A 7 북 동 000 090\n",
+ "39 201 5 B 4 북 남 000 180\n",
+ "40 202 1 A 6 동 서 090 270\n",
+ "41 202 1 B 2 서 동 270 090\n",
+ "42 202 2 A 17 NaN NaN NaN NaN\n",
+ "43 202 2 B 18 NaN NaN NaN NaN\n",
+ "44 206 1 A 8 남 북 180 000\n",
+ "45 206 1 B 4 북 남 000 180\n",
+ "46 206 2 A 17 NaN NaN NaN NaN\n",
+ "47 206 2 B 18 NaN NaN NaN NaN\n",
+ "48 206 3 A 8 남 북 180 000\n",
+ "49 206 3 B 4 북 남 000 180\n",
+ "50 206 4 A 17 NaN NaN NaN NaN\n",
+ "51 206 4 B 18 NaN NaN NaN NaN\n",
+ "52 210 1 A 6 동 서 090 270\n",
+ "53 210 1 B 18 NaN NaN NaN NaN\n",
+ "54 210 2 A 5 서 북 268 000\n",
+ "55 210 2 B 2 서 동 270 090\n",
+ "56 210 3 A 7 북 동 359 090\n",
+ "57 210 3 B 4 북 남 000 180\n",
+ "58 210 4 A 8 남 북 180 000\n",
+ "59 210 4 B 3 남 서 180 270"
+ ]
+ },
+ "execution_count": 46,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# [방위각정보] 불러오기, 계층화, 병합\n",
+ "# 불러오기\n",
+ "dtype_dict = {f'angle_{alph}{j}':'str' for alph in ['A', 'B'] for j in range(1,9)}\n",
+ "angle_original = pd.read_csv('../../Data/tables/angle.csv', index_col=0, dtype = dtype_dict)\n",
+ "# 계층화\n",
+ "angle = []\n",
+ "for i, row in angle_original.iterrows():\n",
+ " angle_codes = row[[f'angle_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " new = pd.DataFrame({'inter_no':[row.inter_no] * 16, 'phase_no':list(range(1, 9))*2, 'ring_type':['A'] * 8 + ['B'] * 8, 'angle_code':angle_codes.to_list()})\n",
+ " angle.append(new)\n",
+ "angle = pd.concat(angle)\n",
+ "angle = angle.dropna().reset_index(drop=True)\n",
+ "# 병합\n",
+ "six_chars = angle.angle_code.apply(lambda x:len(x)==6)\n",
+ "angle.loc[six_chars,'inc_angle'] = angle.angle_code.apply(lambda x:x[:3])\n",
+ "angle.loc[six_chars,'out_angle'] = angle.angle_code.apply(lambda x:x[3:])\n",
+ "angle = angle.drop('angle_code', axis=1)\n",
+ "match4 = pd.merge(match3, angle, how='left', left_on=['inter_no', 'phase_no', 'ring_type'],\n",
+ " right_on=['inter_no', 'phase_no', 'ring_type']).drop_duplicates()\n",
+ "match4"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 47,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 179 | \n",
+ " 004 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 003 | \n",
+ " 176 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 001 | \n",
+ " 095 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 179 | \n",
+ " 270 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 8 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " -571542810_01 | \n",
+ " -571542797_02.99 | \n",
+ " i1 | \n",
+ "
\n",
+ " \n",
+ " 9 | \n",
+ " 176 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 359 | \n",
+ " 180 | \n",
+ " 571542797_02.99 | \n",
+ " 571542810_01 | \n",
+ " i1 | \n",
+ "
\n",
+ " \n",
+ " 10 | \n",
+ " 176 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " -571542810_01 | \n",
+ " -571542797_02.99 | \n",
+ " i1 | \n",
+ "
\n",
+ " \n",
+ " 11 | \n",
+ " 176 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " -571542810_01 | \n",
+ " 571543469_01 | \n",
+ " i1 | \n",
+ "
\n",
+ " \n",
+ " 12 | \n",
+ " 176 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 356 | \n",
+ " 571543469_02 | \n",
+ " -571542797_02.99 | \n",
+ " i1 | \n",
+ "
\n",
+ " \n",
+ " 13 | \n",
+ " 176 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i1 | \n",
+ "
\n",
+ " \n",
+ " 14 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " -571542809_01 | \n",
+ " 571542811_01 | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 15 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 001 | \n",
+ " 176 | \n",
+ " 571542811_02 | \n",
+ " 571542809_01 | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 16 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ " 571542811_02 | \n",
+ " 571542107_01 | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 17 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 179 | \n",
+ " 270 | \n",
+ " -571542809_01 | \n",
+ " 571542809_01 | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 18 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 19 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 20 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ " -571542809_01 | \n",
+ " 571542811_01 | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 21 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " 571542107_02 | \n",
+ " 571542809_01 | \n",
+ " i2 | \n",
+ "
\n",
+ " \n",
+ " 22 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " 571540304_02 | \n",
+ " 571556450_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 23 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " 571556450_02 | \n",
+ " 571540304_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 24 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ " 571556450_02 | \n",
+ " 571500475_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 25 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " 571540304_02 | \n",
+ " 571540303_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 26 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 000 | \n",
+ " 571540303_02.21 | \n",
+ " 571556450_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 27 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571540303_02.21 | \n",
+ " 571500475_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 28 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " -571500475_01 | \n",
+ " 571540303_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 29 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " -571500475_01 | \n",
+ " 571540304_01 | \n",
+ " i3 | \n",
+ "
\n",
+ " \n",
+ " 30 | \n",
+ " 201 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " -571500569_01 | \n",
+ " 571500583_02 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 31 | \n",
+ " 201 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " -571500569_01 | \n",
+ " 571500618_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 32 | \n",
+ " 201 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 000 | \n",
+ " 571500618_02 | \n",
+ " 571500583_02 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 33 | \n",
+ " 201 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571500618_02 | \n",
+ " 571500617_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 34 | \n",
+ " 201 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " 571500617_02 | \n",
+ " 571500618_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 35 | \n",
+ " 201 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571500618_02 | \n",
+ " 571500617_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 36 | \n",
+ " 201 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " 571500617_02 | \n",
+ " 571500618_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 37 | \n",
+ " 201 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " 571500617_02 | \n",
+ " 571500569_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 38 | \n",
+ " 201 | \n",
+ " 5 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ " 571500583_01 | \n",
+ " 571500617_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 39 | \n",
+ " 201 | \n",
+ " 5 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " 571500583_01 | \n",
+ " 571500569_01 | \n",
+ " i8 | \n",
+ "
\n",
+ " \n",
+ " 40 | \n",
+ " 202 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " 571510152_02 | \n",
+ " -571510152_01 | \n",
+ " i9 | \n",
+ "
\n",
+ " \n",
+ " 41 | \n",
+ " 202 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571510152_01 | \n",
+ " 571510152_01.65 | \n",
+ " i9 | \n",
+ "
\n",
+ " \n",
+ " 42 | \n",
+ " 202 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i9 | \n",
+ "
\n",
+ " \n",
+ " 43 | \n",
+ " 202 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i9 | \n",
+ "
\n",
+ " \n",
+ " 44 | \n",
+ " 206 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " -571511538_02 | \n",
+ " 571542073_02 | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 45 | \n",
+ " 206 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " 571542073_01 | \n",
+ " 571511538_02 | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 46 | \n",
+ " 206 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 47 | \n",
+ " 206 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 48 | \n",
+ " 206 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " -571511538_02 | \n",
+ " 571542073_02 | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 49 | \n",
+ " 206 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " 571542073_01 | \n",
+ " 571511538_02 | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 50 | \n",
+ " 206 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 51 | \n",
+ " 206 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i7 | \n",
+ "
\n",
+ " \n",
+ " 52 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " -571542115_01 | \n",
+ " 571500535_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 53 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 54 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ " 571500535_02.18 | \n",
+ " 571511538_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 55 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571500535_02.18 | \n",
+ " 571542115_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 56 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 359 | \n",
+ " 090 | \n",
+ " 571511538_02.121 | \n",
+ " 571542115_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 57 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " 571511538_02.121 | \n",
+ " 571500585_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 58 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " 571500585_02 | \n",
+ " 571511538_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 59 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " 571500585_02 | \n",
+ " 571500535_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 175 1 A 8 남 북 179 004 \n",
+ "1 175 1 B 4 북 남 003 176 \n",
+ "2 175 2 A 7 북 동 001 095 \n",
+ "3 175 2 B 3 남 서 179 270 \n",
+ "4 175 3 A 6 동 서 090 270 \n",
+ "5 175 3 B 1 동 남 090 180 \n",
+ "6 175 4 A 5 서 북 268 000 \n",
+ "7 175 4 B 2 서 동 270 090 \n",
+ "8 176 1 A 8 남 북 180 000 \n",
+ "9 176 1 B 4 북 남 359 180 \n",
+ "10 176 2 A 8 남 북 180 000 \n",
+ "11 176 2 B 3 남 서 180 270 \n",
+ "12 176 3 A 5 서 북 270 356 \n",
+ "13 176 3 B 18 NaN NaN NaN NaN \n",
+ "14 177 1 A 8 남 북 180 000 \n",
+ "15 177 1 B 4 북 남 001 176 \n",
+ "16 177 2 A 7 북 동 000 090 \n",
+ "17 177 2 B 3 남 서 179 270 \n",
+ "18 177 3 A 17 NaN NaN NaN NaN \n",
+ "19 177 3 B 18 NaN NaN NaN NaN \n",
+ "20 177 4 A 5 서 북 268 000 \n",
+ "21 177 4 B 1 동 남 090 180 \n",
+ "22 178 1 A 8 남 북 180 000 \n",
+ "23 178 1 B 4 북 남 000 180 \n",
+ "24 178 2 A 7 북 동 000 090 \n",
+ "25 178 2 B 3 남 서 180 270 \n",
+ "26 178 3 A 5 서 북 270 000 \n",
+ "27 178 3 B 2 서 동 270 090 \n",
+ "28 178 4 A 6 동 서 090 270 \n",
+ "29 178 4 B 1 동 남 090 180 \n",
+ "30 201 1 A 8 남 북 180 000 \n",
+ "31 201 1 B 3 남 서 180 270 \n",
+ "32 201 2 A 5 서 북 270 000 \n",
+ "33 201 2 B 2 서 동 270 090 \n",
+ "34 201 3 A 6 동 서 090 270 \n",
+ "35 201 3 B 2 서 동 270 090 \n",
+ "36 201 4 A 6 동 서 090 270 \n",
+ "37 201 4 B 1 동 남 090 180 \n",
+ "38 201 5 A 7 북 동 000 090 \n",
+ "39 201 5 B 4 북 남 000 180 \n",
+ "40 202 1 A 6 동 서 090 270 \n",
+ "41 202 1 B 2 서 동 270 090 \n",
+ "42 202 2 A 17 NaN NaN NaN NaN \n",
+ "43 202 2 B 18 NaN NaN NaN NaN \n",
+ "44 206 1 A 8 남 북 180 000 \n",
+ "45 206 1 B 4 북 남 000 180 \n",
+ "46 206 2 A 17 NaN NaN NaN NaN \n",
+ "47 206 2 B 18 NaN NaN NaN NaN \n",
+ "48 206 3 A 8 남 북 180 000 \n",
+ "49 206 3 B 4 북 남 000 180 \n",
+ "50 206 4 A 17 NaN NaN NaN NaN \n",
+ "51 206 4 B 18 NaN NaN NaN NaN \n",
+ "52 210 1 A 6 동 서 090 270 \n",
+ "53 210 1 B 18 NaN NaN NaN NaN \n",
+ "54 210 2 A 5 서 북 268 000 \n",
+ "55 210 2 B 2 서 동 270 090 \n",
+ "56 210 3 A 7 북 동 359 090 \n",
+ "57 210 3 B 4 북 남 000 180 \n",
+ "58 210 4 A 8 남 북 180 000 \n",
+ "59 210 4 B 3 남 서 180 270 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 -571542797_02 571500487_01 i0 \n",
+ "1 -571500487_01 571542797_02 i0 \n",
+ "2 -571500487_01 571545870_01 i0 \n",
+ "3 -571542797_02 571510153_01 i0 \n",
+ "4 571545870_02 571510153_01 i0 \n",
+ "5 571545870_02 571542797_02 i0 \n",
+ "6 571510153_02 571500487_01 i0 \n",
+ "7 571510153_02 571545870_01 i0 \n",
+ "8 -571542810_01 -571542797_02.99 i1 \n",
+ "9 571542797_02.99 571542810_01 i1 \n",
+ "10 -571542810_01 -571542797_02.99 i1 \n",
+ "11 -571542810_01 571543469_01 i1 \n",
+ "12 571543469_02 -571542797_02.99 i1 \n",
+ "13 NaN NaN i1 \n",
+ "14 -571542809_01 571542811_01 i2 \n",
+ "15 571542811_02 571542809_01 i2 \n",
+ "16 571542811_02 571542107_01 i2 \n",
+ "17 -571542809_01 571542809_01 i2 \n",
+ "18 NaN NaN i2 \n",
+ "19 NaN NaN i2 \n",
+ "20 -571542809_01 571542811_01 i2 \n",
+ "21 571542107_02 571542809_01 i2 \n",
+ "22 571540304_02 571556450_01 i3 \n",
+ "23 571556450_02 571540304_01 i3 \n",
+ "24 571556450_02 571500475_01 i3 \n",
+ "25 571540304_02 571540303_01 i3 \n",
+ "26 571540303_02.21 571556450_01 i3 \n",
+ "27 571540303_02.21 571500475_01 i3 \n",
+ "28 -571500475_01 571540303_01 i3 \n",
+ "29 -571500475_01 571540304_01 i3 \n",
+ "30 -571500569_01 571500583_02 i8 \n",
+ "31 -571500569_01 571500618_01 i8 \n",
+ "32 571500618_02 571500583_02 i8 \n",
+ "33 571500618_02 571500617_01 i8 \n",
+ "34 571500617_02 571500618_01 i8 \n",
+ "35 571500618_02 571500617_01 i8 \n",
+ "36 571500617_02 571500618_01 i8 \n",
+ "37 571500617_02 571500569_01 i8 \n",
+ "38 571500583_01 571500617_01 i8 \n",
+ "39 571500583_01 571500569_01 i8 \n",
+ "40 571510152_02 -571510152_01 i9 \n",
+ "41 571510152_01 571510152_01.65 i9 \n",
+ "42 NaN NaN i9 \n",
+ "43 NaN NaN i9 \n",
+ "44 -571511538_02 571542073_02 i7 \n",
+ "45 571542073_01 571511538_02 i7 \n",
+ "46 NaN NaN i7 \n",
+ "47 NaN NaN i7 \n",
+ "48 -571511538_02 571542073_02 i7 \n",
+ "49 571542073_01 571511538_02 i7 \n",
+ "50 NaN NaN i7 \n",
+ "51 NaN NaN i7 \n",
+ "52 -571542115_01 571500535_01 i6 \n",
+ "53 NaN NaN i6 \n",
+ "54 571500535_02.18 571511538_01 i6 \n",
+ "55 571500535_02.18 571542115_01 i6 \n",
+ "56 571511538_02.121 571542115_01 i6 \n",
+ "57 571511538_02.121 571500585_01 i6 \n",
+ "58 571500585_02 571511538_01 i6 \n",
+ "59 571500585_02 571500535_01 i6 "
+ ]
+ },
+ "execution_count": 47,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# [네트워크], [교차로-노드 매칭], [교차로정보] 불러오기\n",
+ "net = sumolib.net.readNet('../../Data/networks/SN_sample.net.xml')\n",
+ "inter_node = pd.read_csv('../../Data/tables/inter_node.csv', index_col=0)\n",
+ "inter_info = pd.read_csv('../../Data/tables/inter_info.csv', index_col=0)\n",
+ "\n",
+ "inter_node1 = inter_node[inter_node.inter_type == 'parent'].drop('inter_type', axis=1)\n",
+ "inter_info1 = inter_info[['inter_no', 'inter_lat', 'inter_lon']]\n",
+ "inter = pd.merge(inter_node1, inter_info1, how='left', left_on=['inter_no'],\n",
+ " right_on=['inter_no']).drop_duplicates()\n",
+ "\n",
+ "inter2node = dict(zip(inter['inter_no'], inter['node_id']))\n",
+ "\n",
+ "match5 = match4.copy()\n",
+ "# 진입진출ID 매칭\n",
+ "for index, row in match5.iterrows():\n",
+ " node_id = inter2node[row.inter_no]\n",
+ " node = net.getNode(node_id)\n",
+ " # 교차로의 모든 (from / to) edges\n",
+ " inc_edges = [edge for edge in node.getIncoming() if edge.getFunction() == ''] # incoming edges\n",
+ " out_edges = [edge for edge in node.getOutgoing() if edge.getFunction() == ''] # outgoing edges\n",
+ " # 교차로의 모든 (from / to) directions\n",
+ " inc_dirs = []\n",
+ " for inc_edge in inc_edges:\n",
+ " start = inc_edge.getShape()[-2]\n",
+ " end = inc_edge.getShape()[-1]\n",
+ " inc_dir = np.array(end) - np.array(start)\n",
+ " inc_dir = inc_dir / (inc_dir ** 2).sum() ** 0.5\n",
+ " inc_dirs.append(inc_dir)\n",
+ " out_dirs = []\n",
+ " for out_edge in out_edges:\n",
+ " start = out_edge.getShape()[0]\n",
+ " end = out_edge.getShape()[1]\n",
+ " out_dir = np.array(end) - np.array(start)\n",
+ " out_dir = out_dir / (out_dir ** 2).sum() ** 0.5\n",
+ " out_dirs.append(out_dir)\n",
+ " # 진입각, 진출각 불러오기\n",
+ " if not pd.isna(row.inc_angle):\n",
+ " inc_angle = int(row.inc_angle)\n",
+ " out_angle = int(row.out_angle)\n",
+ " # 방위각을 일반각으로 가공, 라디안 변환, 단위벡터로 변환\n",
+ " inc_angle = (-90 - inc_angle) % 360\n",
+ " inc_angle = inc_angle * np.pi / 180.\n",
+ " inc_dir_true = np.array([np.cos(inc_angle), np.sin(inc_angle)])\n",
+ " out_angle = (90 - out_angle) % 360\n",
+ " out_angle = out_angle * np.pi / 180.\n",
+ " out_dir_true = np.array([np.cos(out_angle), np.sin(out_angle)])\n",
+ " # 매칭 엣지 반환\n",
+ " inc_index = np.array([np.dot(inc_dir, inc_dir_true) for inc_dir in inc_dirs]).argmax()\n",
+ " out_index = np.array([np.dot(out_dir, out_dir_true) for out_dir in out_dirs]).argmax()\n",
+ " inc_edge_id = inc_edges[inc_index].getID()\n",
+ " out_edge_id = out_edges[out_index].getID()\n",
+ " match5.at[index, 'inc_edge'] = inc_edge_id\n",
+ " match5.at[index, 'out_edge'] = out_edge_id\n",
+ "match5['node_id'] = match5['inter_no'].map(inter2node)\n",
+ "match5 = match5.sort_values(by=['inter_no','phase_no','ring_type']).reset_index(drop=True)\n",
+ "match5"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 48,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array(['u00', 'u20', 'u30', 'u31', 'u32', 'u60'], dtype=object)"
+ ]
+ },
+ "execution_count": 48,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# 유턴/연동교차로에 대하여 진입ID, 진출ID 부여\n",
+ "node2inter = dict(zip(inter_node['node_id'], inter_node['inter_no']))\n",
+ "\n",
+ "uturn = pd.read_csv('../../Data/tables/child_uturn.csv')\n",
+ "coord = pd.read_csv('../../Data/tables/child_coord.csv')\n",
+ "\n",
+ "child_ids = inter_node[inter_node.inter_type=='child'].node_id.unique()\n",
+ "ch2pa = {} # child to parent\n",
+ "for child_id in child_ids:\n",
+ " parent_no = inter_node[inter_node.node_id==child_id].inter_no.iloc[0]\n",
+ " sub_inter_node = inter_node[inter_node.inter_no==parent_no]\n",
+ " ch2pa[child_id] = sub_inter_node[sub_inter_node.inter_type=='parent'].iloc[0].node_id\n",
+ "directions = ['북', '북동', '동', '남동', '남', '남서', '서', '북서'] # 정북기준 시계방향으로 8방향\n",
+ "u_ids = uturn.child_id.unique()\n",
+ "u_ids"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 49,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "u00 i0 좌회전시 북\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 179 | \n",
+ " 004 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 003 | \n",
+ " 176 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 19 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 001 | \n",
+ " 095 | \n",
+ " 571500487_02 | \n",
+ " 571500487_01.32 | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 179 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u00 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 175 1 A 8 남 북 179 004 \n",
+ "1 175 1 B 4 북 남 003 176 \n",
+ "2 175 2 A 19 북 동 001 095 \n",
+ "3 175 2 B 3 남 서 179 270 \n",
+ "4 175 3 A 6 동 서 090 270 \n",
+ "5 175 3 B 1 동 남 090 180 \n",
+ "6 175 4 A 5 서 북 268 000 \n",
+ "7 175 4 B 2 서 동 270 090 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 NaN NaN u00 \n",
+ "1 NaN NaN u00 \n",
+ "2 571500487_02 571500487_01.32 u00 \n",
+ "3 NaN NaN u00 \n",
+ "4 NaN NaN u00 \n",
+ "5 NaN NaN u00 \n",
+ "6 NaN NaN u00 \n",
+ "7 NaN NaN u00 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "u20 i2 보행신호시 북\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 177 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 001 | \n",
+ " 176 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 177 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 179 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 17 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 571542810_01.51 | \n",
+ " 571542810_02 | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 177 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 177 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u20 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 177 1 A 8 남 북 180 000 \n",
+ "1 177 1 B 4 북 남 001 176 \n",
+ "2 177 2 A 7 북 동 000 090 \n",
+ "3 177 2 B 3 남 서 179 270 \n",
+ "4 177 3 A 17 NaN NaN NaN NaN \n",
+ "5 177 3 B 18 NaN NaN NaN NaN \n",
+ "6 177 4 A 5 서 북 268 000 \n",
+ "7 177 4 B 1 동 남 090 180 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 NaN NaN u20 \n",
+ "1 NaN NaN u20 \n",
+ "2 NaN NaN u20 \n",
+ "3 NaN NaN u20 \n",
+ "4 571542810_01.51 571542810_02 u20 \n",
+ "5 NaN NaN u20 \n",
+ "6 NaN NaN u20 \n",
+ "7 NaN NaN u20 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "u30 i3 보행신호시 북\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 19 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " 571556452_01 | \n",
+ " 571556452_02 | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u30 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 178 1 A 8 남 북 180 000 \n",
+ "1 178 1 B 4 북 남 000 180 \n",
+ "2 178 2 A 7 북 동 000 090 \n",
+ "3 178 2 B 3 남 서 180 270 \n",
+ "4 178 3 A 5 서 북 270 000 \n",
+ "5 178 3 B 2 서 동 270 090 \n",
+ "6 178 4 A 19 동 서 090 270 \n",
+ "7 178 4 B 1 동 남 090 180 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 NaN NaN u30 \n",
+ "1 NaN NaN u30 \n",
+ "2 NaN NaN u30 \n",
+ "3 NaN NaN u30 \n",
+ "4 NaN NaN u30 \n",
+ "5 NaN NaN u30 \n",
+ "6 571556452_01 571556452_02 u30 \n",
+ "7 NaN NaN u30 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "u31 i3 보행신호시 동\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 19 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " 571500475_02 | \n",
+ " 571500475_01.26 | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u31 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 178 1 A 19 남 북 180 000 \n",
+ "1 178 1 B 4 북 남 000 180 \n",
+ "2 178 2 A 7 북 동 000 090 \n",
+ "3 178 2 B 3 남 서 180 270 \n",
+ "4 178 3 A 5 서 북 270 000 \n",
+ "5 178 3 B 2 서 동 270 090 \n",
+ "6 178 4 A 6 동 서 090 270 \n",
+ "7 178 4 B 1 동 남 090 180 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 571500475_02 571500475_01.26 u31 \n",
+ "1 NaN NaN u31 \n",
+ "2 NaN NaN u31 \n",
+ "3 NaN NaN u31 \n",
+ "4 NaN NaN u31 \n",
+ "5 NaN NaN u31 \n",
+ "6 NaN NaN u31 \n",
+ "7 NaN NaN u31 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "u32 i3 보행신호시 서\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 19 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " 571540303_02 | \n",
+ " -571540303_02 | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 000 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 270 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 090 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u32 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 178 1 A 8 남 북 180 000 \n",
+ "1 178 1 B 19 북 남 000 180 \n",
+ "2 178 2 A 7 북 동 000 090 \n",
+ "3 178 2 B 3 남 서 180 270 \n",
+ "4 178 3 A 5 서 북 270 000 \n",
+ "5 178 3 B 2 서 동 270 090 \n",
+ "6 178 4 A 6 동 서 090 270 \n",
+ "7 178 4 B 1 동 남 090 180 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 NaN NaN u32 \n",
+ "1 571540303_02 -571540303_02 u32 \n",
+ "2 NaN NaN u32 \n",
+ "3 NaN NaN u32 \n",
+ "4 NaN NaN u32 \n",
+ "5 NaN NaN u32 \n",
+ "6 NaN NaN u32 \n",
+ "7 NaN NaN u32 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "u60 i6 직좌시 서\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 210 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 18 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 19 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 268 | \n",
+ " 000 | \n",
+ " 571500535_02 | \n",
+ " -571500535_02 | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 19 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571500535_02 | \n",
+ " -571500535_02 | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 359 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 210 1 A 6 동 서 090 270 \n",
+ "1 210 1 B 18 NaN NaN NaN NaN \n",
+ "2 210 2 A 19 서 북 268 000 \n",
+ "3 210 2 B 19 서 동 270 090 \n",
+ "4 210 3 A 7 북 동 359 090 \n",
+ "5 210 3 B 4 북 남 000 180 \n",
+ "6 210 4 A 8 남 북 180 000 \n",
+ "7 210 4 B 3 남 서 180 270 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 NaN NaN u60 \n",
+ "1 NaN NaN u60 \n",
+ "2 571500535_02 -571500535_02 u60 \n",
+ "3 571500535_02 -571500535_02 u60 \n",
+ "4 NaN NaN u60 \n",
+ "5 NaN NaN u60 \n",
+ "6 NaN NaN u60 \n",
+ "7 NaN NaN u60 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 178 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 571542116_01 | \n",
+ " -571542116_02.96 | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 178 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 571542116_02.96 | \n",
+ " 571542116_02.164 | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 571542116_01 | \n",
+ " -571542116_02.96 | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 178 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 571542116_02.96 | \n",
+ " 571542116_02.164 | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 571542116_01 | \n",
+ " -571542116_02.96 | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 178 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 20 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " 571542116_02.96 | \n",
+ " 571542116_02.164 | \n",
+ " c30 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle \\\n",
+ "0 178 1 A 20 NaN NaN NaN \n",
+ "1 178 1 B 20 NaN NaN NaN \n",
+ "2 178 2 A 20 NaN NaN NaN \n",
+ "3 178 2 B 20 NaN NaN NaN \n",
+ "4 178 3 A 20 NaN NaN NaN \n",
+ "5 178 3 B 20 NaN NaN NaN \n",
+ "6 178 4 A 20 NaN NaN NaN \n",
+ "7 178 4 B 20 NaN NaN NaN \n",
+ "\n",
+ " out_angle inc_edge out_edge node_id \n",
+ "0 NaN NaN NaN c30 \n",
+ "1 NaN NaN NaN c30 \n",
+ "2 NaN 571542116_01 -571542116_02.96 c30 \n",
+ "3 NaN 571542116_02.96 571542116_02.164 c30 \n",
+ "4 NaN 571542116_01 -571542116_02.96 c30 \n",
+ "5 NaN 571542116_02.96 571542116_02.164 c30 \n",
+ "6 NaN 571542116_01 -571542116_02.96 c30 \n",
+ "7 NaN 571542116_02.96 571542116_02.164 c30 "
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phase_no | \n",
+ " ring_type | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_angle | \n",
+ " out_angle | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 179 | \n",
+ " 004 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 003 | \n",
+ " 176 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 001 | \n",
+ " 095 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 179 | \n",
+ " 270 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 6 | \n",
+ " 동 | \n",
+ " 서 | \n",
+ " 090 | \n",
+ " 270 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 210 | \n",
+ " 2 | \n",
+ " B | \n",
+ " 19 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 270 | \n",
+ " 090 | \n",
+ " 571500535_02 | \n",
+ " -571500535_02 | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " A | \n",
+ " 7 | \n",
+ " 북 | \n",
+ " 동 | \n",
+ " 359 | \n",
+ " 090 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 5 | \n",
+ " 210 | \n",
+ " 3 | \n",
+ " B | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " 000 | \n",
+ " 180 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 6 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " A | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 180 | \n",
+ " 000 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ " 7 | \n",
+ " 210 | \n",
+ " 4 | \n",
+ " B | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " 180 | \n",
+ " 270 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " u60 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
116 rows × 11 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
+ "0 175 1 A 8 남 북 179 004 \n",
+ "1 175 1 B 4 북 남 003 176 \n",
+ "2 175 2 A 7 북 동 001 095 \n",
+ "3 175 2 B 3 남 서 179 270 \n",
+ "4 175 3 A 6 동 서 090 270 \n",
+ ".. ... ... ... ... ... ... ... ... \n",
+ "3 210 2 B 19 서 동 270 090 \n",
+ "4 210 3 A 7 북 동 359 090 \n",
+ "5 210 3 B 4 북 남 000 180 \n",
+ "6 210 4 A 8 남 북 180 000 \n",
+ "7 210 4 B 3 남 서 180 270 \n",
+ "\n",
+ " inc_edge out_edge node_id \n",
+ "0 -571542797_02 571500487_01 i0 \n",
+ "1 -571500487_01 571542797_02 i0 \n",
+ "2 -571500487_01 571545870_01 i0 \n",
+ "3 -571542797_02 571510153_01 i0 \n",
+ "4 571545870_02 571510153_01 i0 \n",
+ ".. ... ... ... \n",
+ "3 571500535_02 -571500535_02 u60 \n",
+ "4 NaN NaN u60 \n",
+ "5 NaN NaN u60 \n",
+ "6 NaN NaN u60 \n",
+ "7 NaN NaN u60 \n",
+ "\n",
+ "[116 rows x 11 columns]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# 유턴/연동교차로에 대하여 진입ID, 진출ID 부여\n",
+ "node2inter = dict(zip(inter_node['node_id'], inter_node['inter_no']))\n",
+ "\n",
+ "uturn = pd.read_csv('../../Data/tables/child_uturn.csv')\n",
+ "coord = pd.read_csv('../../Data/tables/child_coord.csv')\n",
+ "child_ids = inter_node[inter_node.inter_type=='child'].node_id.unique()\n",
+ "ch2pa = {} # child to parent\n",
+ "for child_id in child_ids:\n",
+ " parent_no = inter_node[inter_node.node_id==child_id].inter_no.iloc[0]\n",
+ " sub_inter_node = inter_node[inter_node.inter_no==parent_no]\n",
+ " ch2pa[child_id] = sub_inter_node[sub_inter_node.inter_type=='parent'].iloc[0].node_id\n",
+ "directions = ['북', '북동', '동', '남동', '남', '남서', '서', '북서'] # 정북기준 시계방향으로 8방향\n",
+ "u_ids = uturn.child_id.unique()\n",
+ "# 각 child uturn node에 대하여 (inc_edge_id, out_edge_id) 부여\n",
+ "cmatches = []\n",
+ "for _, row in uturn.iterrows():\n",
+ " child_id = row.child_id\n",
+ " parent_id = row.parent_id\n",
+ " direction = row.direction\n",
+ " condition = row.condition\n",
+ " inc_edge_id = row.inc_edge\n",
+ " out_edge_id = row.out_edge\n",
+ " ind = directions.index(direction)\n",
+ " if condition == \"좌회전시\":\n",
+ " print(child_id, parent_id, condition, direction)\n",
+ " inc_dire = direction\n",
+ " out_dire_A = out_dire_B = directions[(ind + 2) % len(directions)]\n",
+ " elif condition == \"직진시\":\n",
+ " print(child_id, parent_id, condition, direction)\n",
+ " inc_dire = direction\n",
+ " out_dire_A = out_dire_B = directions[(ind + 4) % len(directions)]\n",
+ " elif condition == \"직좌시\":\n",
+ " print(child_id, parent_id, condition, direction)\n",
+ " inc_dire = direction\n",
+ " out_dire_A = directions[(ind + 2) % len(directions)]\n",
+ " out_dire_B = directions[(ind + 4) % len(directions)]\n",
+ " elif condition == \"보행신호시\":\n",
+ " print(child_id, parent_id, condition, direction)\n",
+ " inc_dire = directions[(ind + 2) % len(directions)]\n",
+ " out_dire_A = directions[(ind - 2) % len(directions)]\n",
+ " out_dire_B = directions[(ind - 2) % len(directions)]\n",
+ " cmatch = match5.copy()[match5.node_id==parent_id] # match dataframe for a child node\n",
+ " cmatch = cmatch.sort_values(by=['phase_no', 'ring_type']).reset_index(drop=True)\n",
+ " cmatch['node_id'] = child_id\n",
+ " cmatch[['inc_edge', 'out_edge']] = np.nan\n",
+ " if condition == '직좌시':\n",
+ " ap = cmatch[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A)].phase_no.iloc[0]\n",
+ " bp = cmatch[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B)].phase_no.iloc[0]\n",
+ " # 직진과 좌회전이 같은 현시에 있는 경우에만 (inc_edge_id, out_edge_id)를 부여한다.\n",
+ " if ap == bp:\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " elif condition == '보행신호시':\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " # 이동류번호가 17(보행신호)이면서 유턴노드방향으로 가는 신호가 없으면 (inc_edge_id, out_edge_id)를 부여한다.\n",
+ " cmatch.loc[(cmatch.move_no==17) & (cmatch.out_dir!=direction), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " else:\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " # 유턴신호의 이동류번호를 19로 부여한다.\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), 'move_no'] = 19\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), 'move_no'] = 19\n",
+ " display(cmatch)\n",
+ " cmatches.append(cmatch)\n",
+ "\n",
+ "# 각 child coordination node에 대하여 (inc_edge_id, out_edge_id) 부여\n",
+ "coord['inter_no'] = coord['parent_id'].map(node2inter)\n",
+ "coord = coord.rename(columns={'child_id':'node_id'})\n",
+ "coord[['inc_dir', 'out_dir', 'inc_angle','out_angle']] = np.nan\n",
+ "coord['move_no'] = 20\n",
+ "coord = coord[['inter_no', 'phase_no', 'ring_type', 'move_no', 'inc_dir', 'out_dir', 'inc_angle','out_angle', 'inc_edge', 'out_edge', 'node_id']]\n",
+ "# display(coord)\n",
+ "cmatches = pd.concat(cmatches)\n",
+ "display(coord)\n",
+ "match6 = pd.concat([match5, cmatches, coord]).drop_duplicates().sort_values(by=['inter_no', 'node_id', 'phase_no', 'ring_type'])\n",
+ "# with pd.option_context('display.max_rows', None, 'display.max_columns', None):\n",
+ "match6.to_csv('../../Data/tables/matching/match6.csv')\n",
+ "display(match6)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 50,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " move_no | \n",
+ " inc_dir | \n",
+ " out_dir | \n",
+ " inc_edge | \n",
+ " out_edge | \n",
+ " node_id | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " 동 | \n",
+ " 남 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " 서 | \n",
+ " 동 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " 남 | \n",
+ " 서 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " 북 | \n",
+ " 남 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " 5 | \n",
+ " 서 | \n",
+ " 북 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " i0 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 69 | \n",
+ " 210 | \n",
+ " 8 | \n",
+ " 남 | \n",
+ " 북 | \n",
+ " 571500585_02 | \n",
+ " 571511538_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 70 | \n",
+ " 210 | \n",
+ " 21 | \n",
+ " 북 | \n",
+ " 서 | \n",
+ " 571511538_02.121 | \n",
+ " 571500535_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 71 | \n",
+ " 210 | \n",
+ " 21 | \n",
+ " 서 | \n",
+ " 남 | \n",
+ " 571500535_02.18 | \n",
+ " 571500585_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 72 | \n",
+ " 210 | \n",
+ " 21 | \n",
+ " 남 | \n",
+ " 동 | \n",
+ " 571500585_02 | \n",
+ " 571542115_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ " 73 | \n",
+ " 210 | \n",
+ " 21 | \n",
+ " 동 | \n",
+ " 북 | \n",
+ " -571542115_01 | \n",
+ " 571511538_01 | \n",
+ " i6 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
74 rows × 7 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no move_no inc_dir out_dir inc_edge out_edge node_id\n",
+ "0 175 1 동 남 571545870_02 571542797_02 i0\n",
+ "1 175 2 서 동 571510153_02 571545870_01 i0\n",
+ "2 175 3 남 서 -571542797_02 571510153_01 i0\n",
+ "3 175 4 북 남 -571500487_01 571542797_02 i0\n",
+ "4 175 5 서 북 571510153_02 571500487_01 i0\n",
+ ".. ... ... ... ... ... ... ...\n",
+ "69 210 8 남 북 571500585_02 571511538_01 i6\n",
+ "70 210 21 북 서 571511538_02.121 571500535_01 i6\n",
+ "71 210 21 서 남 571500535_02.18 571500585_01 i6\n",
+ "72 210 21 남 동 571500585_02 571542115_01 i6\n",
+ "73 210 21 동 북 -571542115_01 571511538_01 i6\n",
+ "\n",
+ "[74 rows x 7 columns]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# 이동류 매칭\n",
+ "# 각 교차로에 대하여, 가능한 모든 이동류(1~18, 21)에 대한 진입·진출엣지ID를 지정한다.\n",
+ "# 모든 이동류에 대해 지정하므로, 시차제시 이전과 다른 이동류가 등장하더라도 항상 진입·진출 엣지 ID를 지정할 수 있다.\n",
+ "match7 = match6.copy()\n",
+ "match7 = match7[['inter_no', 'move_no', 'inc_dir', 'out_dir', 'inc_edge', 'out_edge', 'node_id']]\n",
+ "\n",
+ "parent_ids = sorted(inter_node[inter_node.inter_type=='parent'].node_id.unique())\n",
+ "child_ids = sorted(inter_node[inter_node.inter_type=='child'].node_id.unique())\n",
+ "\n",
+ "# (1) 가능한 (진입방향, 진출방향) 목록 \n",
+ "flows = nema.dropna().apply(lambda row: (row['inc_dir'], row['out_dir']), axis=1).tolist()\n",
+ "# (2) 각 교차로별 방향 목록 : pdires (possible directions)\n",
+ "pdires = {}\n",
+ "for node_id in parent_ids:\n",
+ " dires = match7[match7.node_id == node_id][['inc_dir','out_dir']].values.flatten()\n",
+ " dires = {dire for dire in dires if type(dire)==str}\n",
+ " pdires[node_id] = dires\n",
+ "# (3) 각 (교차로, 진입방향) 별 진입id 목록 : inc2id (incoming direction to incoming edge_id)\n",
+ "inc2id = {}\n",
+ "for node_id in parent_ids:\n",
+ " for inc_dir in pdires[node_id]:\n",
+ " df = match7[(match7.node_id==node_id) & (match7.inc_dir==inc_dir)]\n",
+ " inc2id[(node_id, inc_dir)] = df.inc_edge.iloc[0]\n",
+ "# (4) 각 (교차로, 진출방향) 별 진출id 목록 : out2id (outgoing direction to outgoing edge_id)\n",
+ "out2id = {}\n",
+ "for node_id in parent_ids:\n",
+ " for out_dir in pdires[node_id]:\n",
+ " df = match7[(match7.node_id==node_id) & (match7.out_dir==out_dir)]\n",
+ " out2id[(node_id, out_dir)] = df.out_edge.iloc[0]\n",
+ "# (5) 각 교차로별 가능한 (진입방향, 진출방향) 목록 : pflow (possible flows)\n",
+ "pflow = {}\n",
+ "for node_id in parent_ids:\n",
+ " pflow[node_id] = [flow for flow in flows if set(flow).issubset(pdires[node_id])]\n",
+ "# (6) 가능한 이동류에 대하여 진입id, 진출id 배정 : matching\n",
+ "node2inter = dict(zip(match7['node_id'], match7['inter_no']))\n",
+ "dires_right = ['북', '서', '남', '동', '북'] # ex (북, 서), (서, 남) 등은 우회전 flow\n",
+ "matching = []\n",
+ "for node_id in parent_ids:\n",
+ " inter_no = node2inter[node_id]\n",
+ " # 좌회전과 직진(1 ~ 16)\n",
+ " for (inc_dir, out_dir) in pflow[node_id]:\n",
+ " move_no = nema[(nema.inc_dir==inc_dir) & (nema.out_dir==out_dir)].move_no.iloc[0]\n",
+ " inc_edge = inc2id[(node_id, inc_dir)]\n",
+ " out_edge = out2id[(node_id, out_dir)]\n",
+ " new_row = pd.DataFrame({'inter_no':[inter_no], 'move_no':[move_no],\n",
+ " 'inc_dir':[inc_dir], 'out_dir':[out_dir],\n",
+ " 'inc_edge':[inc_edge], 'out_edge':[out_edge], 'node_id':[node_id]})\n",
+ " matching.append(new_row)\n",
+ " # 보행신호(17), 전적색(18)\n",
+ " new_row = pd.DataFrame({'inter_no':[inter_no] * 2, 'move_no':[17, 18],\n",
+ " 'inc_dir':[None]*2, 'out_dir':[None]*2,\n",
+ " 'inc_edge':[None]*2, 'out_edge':[None]*2, 'node_id':[node_id]*2})\n",
+ " matching.append(new_row)\n",
+ " # 신호우회전(21)\n",
+ " for d in range(len(dires_right)-1):\n",
+ " inc_dir = dires_right[d]\n",
+ " out_dir = dires_right[d+1]\n",
+ " if {inc_dir, out_dir}.issubset(pdires[node_id]):\n",
+ " inc_edge = inc2id[(node_id, inc_dir)]\n",
+ " out_edge = out2id[(node_id, out_dir)]\n",
+ " new_row = pd.DataFrame({'inter_no':[inter_no], 'move_no':[21],\n",
+ " 'inc_dir':[inc_dir], 'out_dir':[out_dir],\n",
+ " 'inc_edge':[inc_edge], 'out_edge':[out_edge], 'node_id':[node_id]})\n",
+ " matching.append(new_row)\n",
+ "matching.append(match7[match7.node_id.isin(child_ids)])\n",
+ "matching = pd.concat(matching)\n",
+ "matching = matching.dropna().sort_values(by=['inter_no', 'node_id', 'move_no']).reset_index(drop=True)\n",
+ "matching['move_no'] = matching['move_no'].astype(int)\n",
+ "matching.to_csv('../../Data/tables/matching/matching.csv')\n",
+ "display(matching)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# B. 5초 간격으로 이동류번호 수집"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 51,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 5초 단위로 이동류번호 저장 및 신호이력에서 유닉스시각 가져와서 표시, 한시간동안의 데이터만 보관\n",
+ "midnight = int(datetime(2024, 1, 5, 0, 0, 0).timestamp())\n",
+ "next_day = int(datetime(2024, 1, 6, 0, 0, 0).timestamp())\n",
+ "fsecs = range(midnight, next_day, 5) # fsecs : unix time by Five SECondS\n",
+ "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 52,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# # time2move = dict(zip(fsecs,moves)) # move : 어느 순간의 이동류정보\n",
+ "# history = pd.read_csv('../../Data/tables/history.csv', index_col=0)\n",
+ "\n",
+ "# time2movement = {} # movement : 어느 순간의, 그 순간으로부터 한시간 동안의 (교차로번호 + 현시별이동류번호 + 시작시간)\n",
+ "# # - 아래 절차를 5초마다 반복\n",
+ "# for fsec in tqdm(fsecs): # fsec : unix time by Five SECond\n",
+ "# # 1. 상태 테이블 조회해서 전체 데이터중 필요데이터(교차로번호, A링 현시번호, A링 이동류번호, B링 현시번호, B링 이동류번호)만 수집 : A\n",
+ "# # move = time2move[fsec]\n",
+ "# move = pd.read_csv(f'../../Data/tables/moves/move_{fsec}.csv', index_col=0)\n",
+ "# # 2. 이력 테이블 조회해서 교차로별로 유닉스시간 최대인 데이터(교차로변호, 종료유닉스타임)만 수집 : B\n",
+ "# recent_histories = [group.iloc[-1:] for _, group in history[history['end_unix'] < fsec].groupby('inter_no')] # 교차로별로 유닉스시간이 최대인 행들\n",
+ "# if not recent_histories:\n",
+ "# rhistory = pd.DataFrame({'inter_no':[], 'end_unix':[]}) # recent history\n",
+ "# else:\n",
+ "# rhistory = pd.concat(recent_histories)\n",
+ "# recent_unix = rhistory[['inter_no', 'end_unix']]\n",
+ "# # 3. 상태 테이블 조회정보(A)와 이력 테이블 조회정보(B) 조인(키값 : 교차로번호) : C\n",
+ "# move = pd.merge(move, recent_unix, how='left', on='inter_no')\n",
+ "# move['end_unix'] = move['end_unix'].fillna(0).astype(int)\n",
+ "# move = move.drop_duplicates()\n",
+ "# # 4. C데이터 프레임에 신규 컬럼(시작 유닉스타임) 생성 후 종료유닉스 타임 값 입력, 종료 유닉스 타임 컬럼 제거\n",
+ "# move = move.rename(columns = {'end_unix':'start_unix'})\n",
+ "# # 5. 이동류 이력정보 READ\n",
+ "# # - CSV 파일로 서버에 저장된 이동류정보를 읽어옴(파일이 없는 경우에는 데이터가 없는 프레임 D 생성)\n",
+ "# try:\n",
+ "# if isinstance(movement, pd.DataFrame): # movement가 존재할 경우 그걸 그대로 씀.\n",
+ "# pass\n",
+ "# else: \n",
+ "# movement = pd.DataFrame()\n",
+ "# except NameError: # movement가 존재하지 않는 경우 생성\n",
+ "# movement = pd.DataFrame()\n",
+ "# # 6. 이동류 이력정보 데이터테이블(D)에 C데이터 add\n",
+ "# movement = pd.concat([movement, move])\n",
+ "# # 7. D데이터 프레임에서 중복데이터 제거(교차로번호, 시작 유닉스타임, A링 현시번호, B링 현시번호 같은 행은 제거)\n",
+ "# movement = movement.drop_duplicates(['inter_no','phas_A','phas_B','start_unix'])\n",
+ "# # 8. D데이터 보관 시간 기준시간을 시작 유닉스 타임의 최대값 - 3600을 값으로 산출하고, 보관 시간 기준시간보다 작은 시작 유닉스 타임을 가진 행은 모두 제거(1시간 데이터만 보관)\n",
+ "# movement = movement[movement.start_unix > fsec - 3600]\n",
+ "# movement = movement.sort_values(by=['start_unix','inter_no','phas_A','phas_B']).reset_index(drop=True)\n",
+ "\n",
+ "# time2movement[fsec] = movement\n",
+ "# movement.to_csv(f'../../Data/tables/movements/movements_{fsec}.csv')\n",
+ "\n",
+ "# # 각 movement들의 길이 시각화\n",
+ "# import matplotlib.pyplot as plt\n",
+ "# plt.plot(fsecs, [len(time2movement[fsec]) for fsec in fsecs])\n",
+ "# plt.close()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# C. 5분 간격으로 신호이력 수집 및 통합테이블 생성"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 53,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "plan = pd.read_csv('../../Data/tables/plan.csv', index_col=0)\n",
+ "history = pd.read_csv('../../Data/tables/history.csv', index_col=0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 54,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " start_hour | \n",
+ " start_minute | \n",
+ " start_seconds | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 1704380400 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 7 | \n",
+ " 0 | \n",
+ " 1704405600 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 9 | \n",
+ " 0 | \n",
+ " 1704412800 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 18 | \n",
+ " 30 | \n",
+ " 1704447000 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " start_hour start_minute start_seconds\n",
+ "0 0 0 1704380400\n",
+ "1 7 0 1704405600\n",
+ "2 9 0 1704412800\n",
+ "3 18 30 1704447000"
+ ]
+ },
+ "execution_count": 54,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# split, isplit : A,B 분리 혹은 통합시 사용될 수 있는 딕셔너리 \n",
+ "splits = {} # splits maps (inter_no, start_hour, start_minute) to split \n",
+ "for i, row in plan.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_hour = row.start_hour\n",
+ " start_minute = row.start_minute\n",
+ " cycle = row.cycle\n",
+ " cums_A = row[[f'dura_A{j}' for j in range(1,9)]].cumsum()\n",
+ " cums_B = row[[f'dura_B{j}' for j in range(1,9)]].cumsum()\n",
+ " splits[(inter_no, start_hour, start_minute)] = {} # split maps (phas_A, phas_B) to k\n",
+ " k = 0\n",
+ " for t in range(cycle):\n",
+ " new_phas_A = len(cums_A[cums_A < t]) + 1\n",
+ " new_phas_B = len(cums_B[cums_B < t]) + 1\n",
+ " if k == 0 or ((new_phas_A, new_phas_B) != (phas_A, phas_B)):\n",
+ " k += 1\n",
+ " phas_A = new_phas_A\n",
+ " phas_B = new_phas_B\n",
+ " splits[(inter_no, start_hour, start_minute)][(phas_A, phas_B)] = k\n",
+ "\n",
+ "isplits = {} # the inverse of splits\n",
+ "for i in splits:\n",
+ " isplits[i] = {splits[i][k]:k for k in splits[i]} # isplit maps k to (phas_A, phas_B)\n",
+ "\n",
+ "# timetable\n",
+ "timetable = plan[['start_hour', 'start_minute']].drop_duplicates()\n",
+ "timetable['start_seconds'] = midnight + timetable['start_hour'] * 3600 + timetable['start_minute'] * 60\n",
+ "timetable"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 55,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2024-01-05 03:20:00\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " start_unix | \n",
+ " dura_A1 | \n",
+ " dura_A2 | \n",
+ " dura_A3 | \n",
+ " dura_A4 | \n",
+ " dura_A5 | \n",
+ " dura_A6 | \n",
+ " dura_A7 | \n",
+ " dura_A8 | \n",
+ " dura_B1 | \n",
+ " dura_B2 | \n",
+ " dura_B3 | \n",
+ " dura_B4 | \n",
+ " dura_B5 | \n",
+ " dura_B6 | \n",
+ " dura_B7 | \n",
+ " dura_B8 | \n",
+ " cycle | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 60 | \n",
+ " 178 | \n",
+ " 1704388800 | \n",
+ " 38 | \n",
+ " 39 | \n",
+ " 40 | \n",
+ " 23 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 38 | \n",
+ " 39 | \n",
+ " 40 | \n",
+ " 23 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ "
\n",
+ " \n",
+ " 60 | \n",
+ " 201 | \n",
+ " 1704388800 | \n",
+ " 24 | \n",
+ " 24 | \n",
+ " 17 | \n",
+ " 58 | \n",
+ " 17 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 24 | \n",
+ " 24 | \n",
+ " 17 | \n",
+ " 58 | \n",
+ " 17 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ "
\n",
+ " \n",
+ " 60 | \n",
+ " 202 | \n",
+ " 1704388800 | \n",
+ " 39 | \n",
+ " 101 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 39 | \n",
+ " 101 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ "
\n",
+ " \n",
+ " 70 | \n",
+ " 206 | \n",
+ " 1704388800 | \n",
+ " 33 | \n",
+ " 35 | \n",
+ " 26 | \n",
+ " 26 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 33 | \n",
+ " 35 | \n",
+ " 26 | \n",
+ " 26 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 120 | \n",
+ "
\n",
+ " \n",
+ " 56 | \n",
+ " 177 | \n",
+ " 1704388801 | \n",
+ " 36 | \n",
+ " 20 | \n",
+ " 68 | \n",
+ " 26 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 36 | \n",
+ " 20 | \n",
+ " 68 | \n",
+ " 26 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 150 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 78 | \n",
+ " 210 | \n",
+ " 1704392159 | \n",
+ " 43 | \n",
+ " 29 | \n",
+ " 56 | \n",
+ " 22 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 24 | \n",
+ " 48 | \n",
+ " 56 | \n",
+ " 22 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 150 | \n",
+ "
\n",
+ " \n",
+ " 84 | \n",
+ " 178 | \n",
+ " 1704392160 | \n",
+ " 38 | \n",
+ " 39 | \n",
+ " 40 | \n",
+ " 23 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 38 | \n",
+ " 39 | \n",
+ " 40 | \n",
+ " 23 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ "
\n",
+ " \n",
+ " 84 | \n",
+ " 201 | \n",
+ " 1704392160 | \n",
+ " 24 | \n",
+ " 24 | \n",
+ " 17 | \n",
+ " 58 | \n",
+ " 17 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 24 | \n",
+ " 24 | \n",
+ " 17 | \n",
+ " 58 | \n",
+ " 17 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ "
\n",
+ " \n",
+ " 98 | \n",
+ " 206 | \n",
+ " 1704392160 | \n",
+ " 33 | \n",
+ " 35 | \n",
+ " 26 | \n",
+ " 26 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 33 | \n",
+ " 35 | \n",
+ " 26 | \n",
+ " 26 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 120 | \n",
+ "
\n",
+ " \n",
+ " 84 | \n",
+ " 202 | \n",
+ " 1704392211 | \n",
+ " 39 | \n",
+ " 101 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 39 | \n",
+ " 101 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 140 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
194 rows × 19 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no start_unix dura_A1 dura_A2 dura_A3 dura_A4 dura_A5 \\\n",
+ "60 178 1704388800 38 39 40 23 0 \n",
+ "60 201 1704388800 24 24 17 58 17 \n",
+ "60 202 1704388800 39 101 0 0 0 \n",
+ "70 206 1704388800 33 35 26 26 0 \n",
+ "56 177 1704388801 36 20 68 26 0 \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "78 210 1704392159 43 29 56 22 0 \n",
+ "84 178 1704392160 38 39 40 23 0 \n",
+ "84 201 1704392160 24 24 17 58 17 \n",
+ "98 206 1704392160 33 35 26 26 0 \n",
+ "84 202 1704392211 39 101 0 0 0 \n",
+ "\n",
+ " dura_A6 dura_A7 dura_A8 dura_B1 dura_B2 dura_B3 dura_B4 dura_B5 \\\n",
+ "60 0 0 0 38 39 40 23 0 \n",
+ "60 0 0 0 24 24 17 58 17 \n",
+ "60 0 0 0 39 101 0 0 0 \n",
+ "70 0 0 0 33 35 26 26 0 \n",
+ "56 0 0 0 36 20 68 26 0 \n",
+ ".. ... ... ... ... ... ... ... ... \n",
+ "78 0 0 0 24 48 56 22 0 \n",
+ "84 0 0 0 38 39 40 23 0 \n",
+ "84 0 0 0 24 24 17 58 17 \n",
+ "98 0 0 0 33 35 26 26 0 \n",
+ "84 0 0 0 39 101 0 0 0 \n",
+ "\n",
+ " dura_B6 dura_B7 dura_B8 cycle \n",
+ "60 0 0 0 140 \n",
+ "60 0 0 0 140 \n",
+ "60 0 0 0 140 \n",
+ "70 0 0 0 120 \n",
+ "56 0 0 0 150 \n",
+ ".. ... ... ... ... \n",
+ "78 0 0 0 150 \n",
+ "84 0 0 0 140 \n",
+ "84 0 0 0 140 \n",
+ "98 0 0 0 120 \n",
+ "84 0 0 0 140 \n",
+ "\n",
+ "[194 rows x 19 columns]"
+ ]
+ },
+ "execution_count": 55,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "m = 40\n",
+ "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
+ "present_time = fmins[m] # 현재시점\n",
+ "print(datetime.fromtimestamp(present_time))\n",
+ "\n",
+ "# 1. 조회시점의 유닉스 타임 이전의 신호이력 수집\n",
+ "rhistory = history.copy() # recent history\n",
+ "rhistory = rhistory[(rhistory.end_unix < present_time)]\n",
+ "# 2. 시작 유닉스 타임컬럼 생성 후 종류 유닉스 타임에서 현시별 현시기간 컬럼의 합을 뺀 값으로 입력\n",
+ "# - 현시시간의 합을 뺀 시간의 +- 10초 이내에 이전 주기정보가 존재하면 그 유닉스 시간을 시작 유닉스시간 값으로 하고, 존재하지 않으면 현시시간의 합을 뺀 유닉스 시간을 시작 유닉스 시간으로 지정\n",
+ "for i, row in rhistory.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " end_unix = row.end_unix\n",
+ " elapsed_time = row[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]].sum() // 2 # 현시시간 합\n",
+ " # 이전 유닉스 존재하지 않음 : 현시시간 합의 차\n",
+ " start_unix = end_unix - elapsed_time\n",
+ " pre_rows = history[:i] # previous rows\n",
+ " if inter_no in pre_rows.inter_no.unique(): # 이전 유닉스 존재\n",
+ " pre_unix = pre_rows[pre_rows.inter_no == inter_no]['end_unix'].iloc[-1] # previous unix time\n",
+ " # 이전 유닉스 존재, abs < 10 : 이전 유닉스\n",
+ " if abs(pre_unix - start_unix) < 10:\n",
+ " start_unix = pre_unix\n",
+ " # 이전 유닉스 존재, abs >=10 : 현시시간 합의 차\n",
+ " else:\n",
+ " pass\n",
+ " rhistory.loc[i, 'start_unix'] = start_unix \n",
+ "rhistory[rhistory.isna()] = 0\n",
+ "rhistory['start_unix'] = rhistory['start_unix'].astype(int)\n",
+ "rhistory[['inter_no', 'start_unix', 'cycle']][rhistory.inter_no==175]\n",
+ "rhistory = rhistory[['inter_no', 'start_unix'] + [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)] + ['cycle']]\n",
+ "\n",
+ "# 2-1. 참값 판단 프로세스\n",
+ "hours = np.array(range(midnight, next_day + 1, 3600)) # 정각에 해당하는 시각들 목록\n",
+ "\n",
+ "def calculate_DS(rhist, curr_unix):\n",
+ " ghour_lt_curr_unix = hours[hours <= curr_unix].max() # the greatest hour less than (or equal to) curr_unix\n",
+ " start_unixes = rhist.start_unix.unique()\n",
+ " start_unixes_lt_ghour = np.sort(start_unixes[start_unixes < ghour_lt_curr_unix]) # start unixes less than ghour_lt_curr_unix\n",
+ " # 기준유닉스(base_unix) : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 start_unix\n",
+ " if list(start_unixes_lt_ghour):\n",
+ " base_unix = start_unixes_lt_ghour[-5]\n",
+ " # start_unixes_lt_ghour가 비었을 경우에는 맨 앞 start_unix로 base_unix를 지정\n",
+ " else:\n",
+ " base_unix = rhist.start_unix.min()\n",
+ " D_n = curr_unix - base_unix\n",
+ " S_n_durs = rhist[(rhist.start_unix > base_unix) & (rhist.start_unix <= curr_unix)] \\\n",
+ " [[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " S_n = S_n_durs.values.sum() // 2\n",
+ " return D_n, S_n\n",
+ "\n",
+ "rhists = []\n",
+ "for inter_no in sorted(rhistory.inter_no.unique()):\n",
+ " rhist = rhistory.copy()[rhistory.inter_no==inter_no]\n",
+ " rhist = rhist.drop_duplicates(subset=['start_unix']).reset_index(drop=True)\n",
+ "\n",
+ " # D_n 및 S_n 값 정의\n",
+ " rhist['D_n'] = 0 # D_n : 시간차이\n",
+ " rhist['S_n'] = 0 # S_n : 현시시간합\n",
+ " for n in range(len(rhist)):\n",
+ " curr_unix = rhist.iloc[n].start_unix # current start_unix\n",
+ " rhist.loc[n, ['D_n', 'S_n']] = calculate_DS(rhist, curr_unix)\n",
+ "\n",
+ " # 이전시각, 현재시각\n",
+ " prev_unix = rhist.loc[0, 'start_unix'] # previous start_unix\n",
+ " curr_unix = rhist.loc[1, 'start_unix'] # current start_unix\n",
+ "\n",
+ " # rhist의 마지막 행에 도달할 때까지 반복\n",
+ " while True:\n",
+ " n = rhist[rhist.start_unix==curr_unix].index[0]\n",
+ " cycle = rhist.loc[n, 'cycle']\n",
+ " D_n = rhist.loc[n, 'D_n']\n",
+ " S_n = rhist.loc[n, 'S_n']\n",
+ " # 참값인 경우\n",
+ " if (abs(D_n - S_n) <= 5):\n",
+ " pass\n",
+ " # 참값이 아닌 경우\n",
+ " else:\n",
+ " # 2-1-1. 결측치 처리 : 인접한 두 start_unix의 차이가 계획된 주기의 두 배보다 크면 결측이 일어났다고 판단, 신호계획의 현시시간으로 \"대체\"\n",
+ " if curr_unix - prev_unix >= 2 * cycle:\n",
+ " # prev_unix를 계획된 주기만큼 늘려가면서 한 행씩 채워나간다.\n",
+ " # (curr_unix와의 차이가 계획된 주기보다 작거나 같아질 때까지)\n",
+ " new_rows = []\n",
+ " while curr_unix - prev_unix > cycle:\n",
+ " prev_unix += cycle\n",
+ " # 신호 계획(prow) 불러오기\n",
+ " start_seconds = np.array(timetable.start_seconds)\n",
+ " idx = (start_seconds <= prev_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[idx].start_hour\n",
+ " start_minute = timetable.iloc[idx].start_minute\n",
+ " prow = plan.copy()[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
+ " # prow에서 필요한 부분을 rhist에 추가\n",
+ " prow['start_unix'] = prev_unix\n",
+ " prow = prow.drop(['start_hour', 'start_minute', 'offset'], axis=1)\n",
+ " cycle = prow.iloc[0].cycle\n",
+ " rhist = pd.concat([rhist, prow])\n",
+ " rhist = rhist.sort_values(by='start_unix').reset_index(drop=True)\n",
+ " n += 1\n",
+ "\n",
+ " # 2-1-2. 이상치 처리 : 비율에 따라 해당 행을 \"삭제\"(R_n <= 0.5) 또는 \"조정\"(R_n > 0.5)한다\n",
+ " R_n = (curr_unix - prev_unix) / cycle # R_n : 비율\n",
+ " # R_n이 0.5보다 작거나 같으면 해당 행을 삭제\n",
+ " if R_n <= 0.5:\n",
+ " rhist = rhist.drop(index=n).reset_index(drop=True)\n",
+ " # 행삭제에 따른 curr_unix, R_n 재정의\n",
+ " curr_unix = rhist.loc[n, 'start_unix']\n",
+ " R_n = (curr_unix - prev_unix) / cycle # R_n : 비율\n",
+ "\n",
+ " # R_n이 0.5보다 크면 해당 행 조정 (비율을 유지한 채로 현시시간 대체)\n",
+ " if R_n > 0.5:\n",
+ " # 신호 계획(prow) 불러오기\n",
+ " start_seconds = np.array(timetable.start_seconds)\n",
+ " idx = (start_seconds <= curr_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[idx].start_hour\n",
+ " start_minute = timetable.iloc[idx].start_minute\n",
+ " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
+ " # 조정된 현시시간 (prow에 R_n을 곱하고 정수로 바꿈)\n",
+ " adjusted_dur = prow.copy()[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] * R_n\n",
+ " int_parts = adjusted_dur.iloc[0].apply(lambda x: int(x))\n",
+ " frac_parts = adjusted_dur.iloc[0] - int_parts\n",
+ " difference = round(adjusted_dur.iloc[0].sum()) - int_parts.sum()\n",
+ " for _ in range(difference): # 소수 부분이 가장 큰 상위 'difference'개의 값에 대해 올림 처리\n",
+ " max_frac_index = frac_parts.idxmax()\n",
+ " int_parts[max_frac_index] += 1\n",
+ " frac_parts[max_frac_index] = 0 # 이미 처리된 항목은 0으로 설정\n",
+ " # rhist에 조정된 현시시간을 반영\n",
+ " rhist.loc[n, [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] = int_parts.values\n",
+ " rhist.loc[n, 'cycle'] = int_parts.sum().sum() // 2\n",
+ "\n",
+ " if n == rhist.index[-1]:\n",
+ " break\n",
+ " prev_unix = curr_unix\n",
+ " curr_unix = rhist.loc[n+1, 'start_unix']\n",
+ " # rhist['start_dt'] = rhist['start_unix'].map(lambda x:datetime.fromtimestamp(x))\n",
+ "\n",
+ " # 생략해도 무방할 코드\n",
+ " rhist = rhist.reset_index(drop=True)\n",
+ " rhist = rhist.sort_values(by=['start_unix'])\n",
+ "\n",
+ " # D_n 및 S_n 값 재정의\n",
+ " for n in range(len(rhist)):\n",
+ " curr_unix = rhist.iloc[n].start_unix # current start_unix\n",
+ " rhist.loc[n, ['D_n', 'S_n']] = calculate_DS(rhist, curr_unix)\n",
+ " rhists.append(rhist)\n",
+ "rhists = pd.concat(rhists).sort_values(by=['start_unix','inter_no'])\n",
+ "rhists = rhists[rhists.start_unix >= present_time - 3600]\n",
+ "rhists = rhists.drop(columns=['D_n', 'S_n'])\n",
+ "rhists"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 56,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# file_path = '../../Data/tables/movements/'\n",
+ "# movements = [pd.read_csv(file_path + file, index_col=0) for file in tqdm(os.listdir(file_path))]\n",
+ "# movements = pd.concat(movements).drop_duplicates()\n",
+ "# movements.to_csv(file_path + 'movements.csv')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 57,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " move_A | \n",
+ " move_B | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 8 | \n",
+ " 175 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " 4 | \n",
+ "
\n",
+ " \n",
+ " 15 | \n",
+ " 175 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 7 | \n",
+ " 3 | \n",
+ "
\n",
+ " \n",
+ " 20 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 6 | \n",
+ " 1 | \n",
+ "
\n",
+ " \n",
+ " 24 | \n",
+ " 175 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 6 | \n",
+ " 2 | \n",
+ "
\n",
+ " \n",
+ " 26 | \n",
+ " 175 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 5 | \n",
+ " 2 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no phas_A phas_B move_A move_B\n",
+ "8 175 1 1 8 4\n",
+ "15 175 2 2 7 3\n",
+ "20 175 3 3 6 1\n",
+ "24 175 3 4 6 2\n",
+ "26 175 4 4 5 2"
+ ]
+ },
+ "execution_count": 57,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "movements = pd.read_csv('../../Data/tables/movements/movements.csv', index_col=0)\n",
+ "movements_wo_start_unix_list = [] # movements without start_unix\n",
+ "for inter_no in sorted(movements.inter_no.unique()):\n",
+ " movements_wo_start_unix = movements[movements.inter_no==inter_no]\n",
+ " movements_wo_start_unix = movements_wo_start_unix[['inter_no', 'phas_A', 'phas_B', 'move_A', 'move_B']]\n",
+ " movements_wo_start_unix = movements_wo_start_unix.drop_duplicates().sort_values(by=['phas_A','phas_B'])\n",
+ " movements_wo_start_unix_list.append(movements_wo_start_unix)\n",
+ "movements_wo_start_unix = pd.concat(movements_wo_start_unix_list)\n",
+ "movements_wo_start_unix.head()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 58,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " start_unix | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " duration | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 178 | \n",
+ " 1704388800 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 38 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 178 | \n",
+ " 1704388800 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 178 | \n",
+ " 1704388800 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 40 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 178 | \n",
+ " 1704388800 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 23 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 201 | \n",
+ " 1704388800 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 24 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 767 | \n",
+ " 206 | \n",
+ " 1704392160 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 35 | \n",
+ "
\n",
+ " \n",
+ " 768 | \n",
+ " 206 | \n",
+ " 1704392160 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 26 | \n",
+ "
\n",
+ " \n",
+ " 769 | \n",
+ " 206 | \n",
+ " 1704392160 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 26 | \n",
+ "
\n",
+ " \n",
+ " 770 | \n",
+ " 202 | \n",
+ " 1704392211 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 39 | \n",
+ "
\n",
+ " \n",
+ " 771 | \n",
+ " 202 | \n",
+ " 1704392211 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 101 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
772 rows × 5 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no start_unix phas_A phas_B duration\n",
+ "0 178 1704388800 1 1 38\n",
+ "1 178 1704388800 2 2 39\n",
+ "2 178 1704388800 3 3 40\n",
+ "3 178 1704388800 4 4 23\n",
+ "4 201 1704388800 1 1 24\n",
+ ".. ... ... ... ... ...\n",
+ "767 206 1704392160 2 2 35\n",
+ "768 206 1704392160 3 3 26\n",
+ "769 206 1704392160 4 4 26\n",
+ "770 202 1704392211 1 1 39\n",
+ "771 202 1704392211 2 2 101\n",
+ "\n",
+ "[772 rows x 5 columns]"
+ ]
+ },
+ "execution_count": 58,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# 계층화된 형태로 변환\n",
+ "hrhists = [] # hierarchied recent history\n",
+ "for i, row in rhists.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_unix = row.start_unix\n",
+ "\n",
+ " ind = (timetable['start_seconds'] <= row.start_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[ind].start_hour\n",
+ " start_minute = timetable.iloc[ind].start_minute\n",
+ " isplit = isplits[(inter_no, start_hour, start_minute)]\n",
+ " phas_As = [isplit[j][0] for j in isplit.keys()]\n",
+ " phas_Bs = [isplit[j][1] for j in isplit.keys()]\n",
+ " durs_A = row[[f'dura_A{j}' for j in range(1,9)]]\n",
+ " durs_B = row[[f'dura_B{j}' for j in range(1,9)]]\n",
+ " durations = []\n",
+ " for j in range(1, len(isplit)+1):\n",
+ " ja = isplit[j][0]\n",
+ " jb = isplit[j][1]\n",
+ " if ja == jb:\n",
+ " durations.append(min(durs_A[ja-1], durs_B[jb-1]))\n",
+ " else:\n",
+ " durations.append(abs(durs_A[ja-1] - durs_B[ja-1]))\n",
+ " new_rows = pd.DataFrame({'inter_no':[inter_no] * len(durations), 'start_unix':[start_unix] * len(durations),\n",
+ " 'phas_A':phas_As, 'phas_B':phas_Bs, 'duration':durations})\n",
+ " hrhists.append(new_rows)\n",
+ "hrhists = pd.concat(hrhists)\n",
+ "hrhists = hrhists.sort_values(by = ['start_unix', 'inter_no', 'phas_A', 'phas_B']).reset_index(drop=True)\n",
+ "hrhists"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 59,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "movement = pd.read_csv(f'../../Data/tables/movements/movements_{present_time}.csv', index_col=0)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 60,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 중복을 제거하고 (inter_no, start_unix) 쌍을 만듭니다.\n",
+ "hrhists_inter_unix = set(hrhists[['inter_no', 'start_unix']].drop_duplicates().itertuples(index=False, name=None))\n",
+ "movement_inter_unix = set(movement[['inter_no', 'start_unix']].drop_duplicates().itertuples(index=False, name=None))\n",
+ "\n",
+ "# hrhists에는 있지만 movement에는 없는 (inter_no, start_unix) 쌍을 찾습니다.\n",
+ "missing_in_movement = hrhists_inter_unix - movement_inter_unix\n",
+ "\n",
+ "# 새로운 행들을 생성합니다.\n",
+ "new_rows = []\n",
+ "for inter_no, start_unix in missing_in_movement:\n",
+ " # movements_wo_start_unix에서 해당 inter_no의 데이터를 찾습니다.\n",
+ " new_row = movements_wo_start_unix[movements_wo_start_unix['inter_no'] == inter_no].copy()\n",
+ " # start_unix 값을 설정합니다.\n",
+ " new_row['start_unix'] = start_unix\n",
+ " new_rows.append(new_row)\n",
+ "\n",
+ "# 새로운 데이터프레임을 생성하고 기존 movement 데이터프레임과 합칩니다.\n",
+ "new_movement = pd.concat(new_rows, ignore_index=True)\n",
+ "movement_updated = pd.concat([movement, new_movement], ignore_index=True)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 61,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " node_id | \n",
+ " start_unix | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " duration | \n",
+ " inc_edge_A | \n",
+ " out_edge_A | \n",
+ " inc_edge_B | \n",
+ " out_edge_B | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704388801 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 36 | \n",
+ " -571542809_01 | \n",
+ " 571542811_01 | \n",
+ " 571542811_02 | \n",
+ " 571542809_01 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704388801 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 20 | \n",
+ " 571542811_02 | \n",
+ " 571542107_01 | \n",
+ " -571542809_01 | \n",
+ " 571542809_01 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704388801 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 68 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 177 | \n",
+ " i2 | \n",
+ " 1704388801 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 26 | \n",
+ " -571542809_01 | \n",
+ " 571542811_01 | \n",
+ " 571542107_02 | \n",
+ " 571542809_01 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 176 | \n",
+ " i1 | \n",
+ " 1704388850 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542810_01 | \n",
+ " -571542797_02.99 | \n",
+ " 571542797_02.99 | \n",
+ " 571542810_01 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 748 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704392160 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 35 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 749 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704392160 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 26 | \n",
+ " -571511538_02 | \n",
+ " 571542073_02 | \n",
+ " 571542073_01 | \n",
+ " 571511538_02 | \n",
+ "
\n",
+ " \n",
+ " 750 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704392160 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 26 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 751 | \n",
+ " 202 | \n",
+ " i9 | \n",
+ " 1704392211 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 39 | \n",
+ " 571510152_02 | \n",
+ " -571510152_01 | \n",
+ " 571510152_01 | \n",
+ " 571510152_01.65 | \n",
+ "
\n",
+ " \n",
+ " 752 | \n",
+ " 202 | \n",
+ " i9 | \n",
+ " 1704392211 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 101 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
757 rows × 10 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no node_id start_unix phas_A phas_B duration inc_edge_A \\\n",
+ "0 177 i2 1704388801 1 1 36 -571542809_01 \n",
+ "1 177 i2 1704388801 2 2 20 571542811_02 \n",
+ "2 177 i2 1704388801 3 3 68 NaN \n",
+ "3 177 i2 1704388801 4 4 26 -571542809_01 \n",
+ "4 176 i1 1704388850 1 1 37 -571542810_01 \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "748 206 i7 1704392160 2 2 35 NaN \n",
+ "749 206 i7 1704392160 3 3 26 -571511538_02 \n",
+ "750 206 i7 1704392160 4 4 26 NaN \n",
+ "751 202 i9 1704392211 1 1 39 571510152_02 \n",
+ "752 202 i9 1704392211 2 2 101 NaN \n",
+ "\n",
+ " out_edge_A inc_edge_B out_edge_B \n",
+ "0 571542811_01 571542811_02 571542809_01 \n",
+ "1 571542107_01 -571542809_01 571542809_01 \n",
+ "2 NaN NaN NaN \n",
+ "3 571542811_01 571542107_02 571542809_01 \n",
+ "4 -571542797_02.99 571542797_02.99 571542810_01 \n",
+ ".. ... ... ... \n",
+ "748 NaN NaN NaN \n",
+ "749 571542073_02 571542073_01 571511538_02 \n",
+ "750 NaN NaN NaN \n",
+ "751 -571510152_01 571510152_01 571510152_01.65 \n",
+ "752 NaN NaN NaN \n",
+ "\n",
+ "[757 rows x 10 columns]"
+ ]
+ },
+ "execution_count": 61,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "movedur = pd.merge(movement_updated, hrhists, how='inner', on=['inter_no', 'start_unix', 'phas_A', 'phas_B']) # movements and durations\n",
+ "movedur = movedur.sort_values(by=['start_unix', 'inter_no', 'phas_A','phas_B'])\n",
+ "movedur = movedur[['inter_no', 'start_unix', 'phas_A', 'phas_B', 'move_A', 'move_B', 'duration']]\n",
+ "\n",
+ "# 이동류 매칭 테이블에서 진입id, 진출id를 가져와서 붙임.\n",
+ "for i, row in movedur.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_unix = row.start_unix\n",
+ " # incoming and outgoing edges A\n",
+ " move_A = row.move_A\n",
+ " if move_A in [17, 18]:\n",
+ " inc_edge_A = np.nan\n",
+ " out_edge_A = np.nan\n",
+ " else:\n",
+ " match_A = matching[(matching.inter_no == inter_no) & (matching.move_no == move_A)].iloc[0]\n",
+ " inc_edge_A = match_A.inc_edge\n",
+ " out_edge_A = match_A.out_edge\n",
+ " movedur.loc[i, ['inc_edge_A', 'out_edge_A']] = [inc_edge_A, out_edge_A]\n",
+ " # incoming and outgoing edges B\n",
+ " move_B = row.move_B\n",
+ " if move_B in [17, 18]:\n",
+ " inc_edge_B = np.nan\n",
+ " out_edge_B = np.nan\n",
+ " else:\n",
+ " match_B = matching[(matching.inter_no == inter_no) & (matching.move_no == move_B)].iloc[0]\n",
+ " inc_edge_B = match_B.inc_edge\n",
+ " out_edge_B = match_B.out_edge\n",
+ " movedur.loc[i, ['inc_edge_B', 'out_edge_B']] = [inc_edge_B, out_edge_B]\n",
+ "\n",
+ "# 이동류 컬럼 제거\n",
+ "movedur = movedur.drop(['move_A', 'move_B'], axis=1)\n",
+ "\n",
+ "histid = movedur.copy() # history with edge ids (incoming and outgoing edge ids)\n",
+ "histid['node_id'] = histid['inter_no'].map(inter2node)\n",
+ "histid = histid[['inter_no', 'node_id', 'start_unix', 'phas_A', 'phas_B', 'duration', 'inc_edge_A', 'out_edge_A', 'inc_edge_B', 'out_edge_B']]\n",
+ "histid = histid[histid.start_unix > present_time - 3600]\n",
+ "histid"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 69,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2024-01-05 03:20:00\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " node_id | \n",
+ " start_unix | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " duration | \n",
+ " inc_edge_A | \n",
+ " out_edge_A | \n",
+ " inc_edge_B | \n",
+ " out_edge_B | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 12 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704388880 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 13 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704388880 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 14 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704388880 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 25 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 15 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704388880 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 30 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 16 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704388880 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 44 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389040 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 45 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389040 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 46 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389040 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 25 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 47 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389040 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 30 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 48 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389040 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 80 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389200 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 81 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389200 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 82 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389200 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 25 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 83 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389200 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 30 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 84 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389200 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 117 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389360 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 118 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389360 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 119 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389360 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 25 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 120 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389360 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 30 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 121 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389360 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 155 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389520 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 156 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389520 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 157 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389520 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 25 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 158 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389520 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 30 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 159 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389520 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 191 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389680 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 192 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389680 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 193 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389680 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 25 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 194 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389680 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 30 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 195 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389680 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 223 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389839 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 224 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389839 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 225 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389839 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 25 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 226 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389839 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 30 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 227 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704389839 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 255 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390000 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 256 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390000 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 257 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390000 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 25 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 258 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390000 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 30 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 259 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390000 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 295 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390160 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 296 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390160 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 297 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390160 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 25 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 298 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390160 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 30 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 299 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390160 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 325 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390320 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 326 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390320 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 327 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390320 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 25 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 328 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390320 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 30 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 329 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390320 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 355 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390480 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 356 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390480 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 357 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390480 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 25 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 358 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390480 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 30 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 359 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390480 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 400 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390640 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 401 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390640 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 402 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390640 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 25 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 403 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390640 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 30 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 404 | \n",
+ " 175 | \n",
+ " i0 | \n",
+ " 1704390640 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no node_id start_unix phas_A phas_B duration inc_edge_A \\\n",
+ "12 175 i0 1704388880 1 1 37 -571542797_02 \n",
+ "13 175 i0 1704388880 2 2 39 -571500487_01 \n",
+ "14 175 i0 1704388880 3 3 25 571545870_02 \n",
+ "15 175 i0 1704388880 3 4 30 571545870_02 \n",
+ "16 175 i0 1704388880 4 4 29 571510153_02 \n",
+ "44 175 i0 1704389040 1 1 37 -571542797_02 \n",
+ "45 175 i0 1704389040 2 2 39 -571500487_01 \n",
+ "46 175 i0 1704389040 3 3 25 571545870_02 \n",
+ "47 175 i0 1704389040 3 4 30 571545870_02 \n",
+ "48 175 i0 1704389040 4 4 29 571510153_02 \n",
+ "80 175 i0 1704389200 1 1 37 -571542797_02 \n",
+ "81 175 i0 1704389200 2 2 39 -571500487_01 \n",
+ "82 175 i0 1704389200 3 3 25 571545870_02 \n",
+ "83 175 i0 1704389200 3 4 30 571545870_02 \n",
+ "84 175 i0 1704389200 4 4 29 571510153_02 \n",
+ "117 175 i0 1704389360 1 1 37 -571542797_02 \n",
+ "118 175 i0 1704389360 2 2 39 -571500487_01 \n",
+ "119 175 i0 1704389360 3 3 25 571545870_02 \n",
+ "120 175 i0 1704389360 3 4 30 571545870_02 \n",
+ "121 175 i0 1704389360 4 4 29 571510153_02 \n",
+ "155 175 i0 1704389520 1 1 37 -571542797_02 \n",
+ "156 175 i0 1704389520 2 2 39 -571500487_01 \n",
+ "157 175 i0 1704389520 3 3 25 571545870_02 \n",
+ "158 175 i0 1704389520 3 4 30 571545870_02 \n",
+ "159 175 i0 1704389520 4 4 29 571510153_02 \n",
+ "191 175 i0 1704389680 1 1 37 -571542797_02 \n",
+ "192 175 i0 1704389680 2 2 39 -571500487_01 \n",
+ "193 175 i0 1704389680 3 3 25 571545870_02 \n",
+ "194 175 i0 1704389680 3 4 30 571545870_02 \n",
+ "195 175 i0 1704389680 4 4 29 571510153_02 \n",
+ "223 175 i0 1704389839 1 1 37 -571542797_02 \n",
+ "224 175 i0 1704389839 2 2 39 -571500487_01 \n",
+ "225 175 i0 1704389839 3 3 25 571545870_02 \n",
+ "226 175 i0 1704389839 3 4 30 571545870_02 \n",
+ "227 175 i0 1704389839 4 4 29 571510153_02 \n",
+ "255 175 i0 1704390000 1 1 37 -571542797_02 \n",
+ "256 175 i0 1704390000 2 2 39 -571500487_01 \n",
+ "257 175 i0 1704390000 3 3 25 571545870_02 \n",
+ "258 175 i0 1704390000 3 4 30 571545870_02 \n",
+ "259 175 i0 1704390000 4 4 29 571510153_02 \n",
+ "295 175 i0 1704390160 1 1 37 -571542797_02 \n",
+ "296 175 i0 1704390160 2 2 39 -571500487_01 \n",
+ "297 175 i0 1704390160 3 3 25 571545870_02 \n",
+ "298 175 i0 1704390160 3 4 30 571545870_02 \n",
+ "299 175 i0 1704390160 4 4 29 571510153_02 \n",
+ "325 175 i0 1704390320 1 1 37 -571542797_02 \n",
+ "326 175 i0 1704390320 2 2 39 -571500487_01 \n",
+ "327 175 i0 1704390320 3 3 25 571545870_02 \n",
+ "328 175 i0 1704390320 3 4 30 571545870_02 \n",
+ "329 175 i0 1704390320 4 4 29 571510153_02 \n",
+ "355 175 i0 1704390480 1 1 37 -571542797_02 \n",
+ "356 175 i0 1704390480 2 2 39 -571500487_01 \n",
+ "357 175 i0 1704390480 3 3 25 571545870_02 \n",
+ "358 175 i0 1704390480 3 4 30 571545870_02 \n",
+ "359 175 i0 1704390480 4 4 29 571510153_02 \n",
+ "400 175 i0 1704390640 1 1 37 -571542797_02 \n",
+ "401 175 i0 1704390640 2 2 39 -571500487_01 \n",
+ "402 175 i0 1704390640 3 3 25 571545870_02 \n",
+ "403 175 i0 1704390640 3 4 30 571545870_02 \n",
+ "404 175 i0 1704390640 4 4 29 571510153_02 \n",
+ "\n",
+ " out_edge_A inc_edge_B out_edge_B \n",
+ "12 571500487_01 -571500487_01 571542797_02 \n",
+ "13 571545870_01 -571542797_02 571510153_01 \n",
+ "14 571510153_01 571545870_02 571542797_02 \n",
+ "15 571510153_01 571510153_02 571545870_01 \n",
+ "16 571500487_01 571510153_02 571545870_01 \n",
+ "44 571500487_01 -571500487_01 571542797_02 \n",
+ "45 571545870_01 -571542797_02 571510153_01 \n",
+ "46 571510153_01 571545870_02 571542797_02 \n",
+ "47 571510153_01 571510153_02 571545870_01 \n",
+ "48 571500487_01 571510153_02 571545870_01 \n",
+ "80 571500487_01 -571500487_01 571542797_02 \n",
+ "81 571545870_01 -571542797_02 571510153_01 \n",
+ "82 571510153_01 571545870_02 571542797_02 \n",
+ "83 571510153_01 571510153_02 571545870_01 \n",
+ "84 571500487_01 571510153_02 571545870_01 \n",
+ "117 571500487_01 -571500487_01 571542797_02 \n",
+ "118 571545870_01 -571542797_02 571510153_01 \n",
+ "119 571510153_01 571545870_02 571542797_02 \n",
+ "120 571510153_01 571510153_02 571545870_01 \n",
+ "121 571500487_01 571510153_02 571545870_01 \n",
+ "155 571500487_01 -571500487_01 571542797_02 \n",
+ "156 571545870_01 -571542797_02 571510153_01 \n",
+ "157 571510153_01 571545870_02 571542797_02 \n",
+ "158 571510153_01 571510153_02 571545870_01 \n",
+ "159 571500487_01 571510153_02 571545870_01 \n",
+ "191 571500487_01 -571500487_01 571542797_02 \n",
+ "192 571545870_01 -571542797_02 571510153_01 \n",
+ "193 571510153_01 571545870_02 571542797_02 \n",
+ "194 571510153_01 571510153_02 571545870_01 \n",
+ "195 571500487_01 571510153_02 571545870_01 \n",
+ "223 571500487_01 -571500487_01 571542797_02 \n",
+ "224 571545870_01 -571542797_02 571510153_01 \n",
+ "225 571510153_01 571545870_02 571542797_02 \n",
+ "226 571510153_01 571510153_02 571545870_01 \n",
+ "227 571500487_01 571510153_02 571545870_01 \n",
+ "255 571500487_01 -571500487_01 571542797_02 \n",
+ "256 571545870_01 -571542797_02 571510153_01 \n",
+ "257 571510153_01 571545870_02 571542797_02 \n",
+ "258 571510153_01 571510153_02 571545870_01 \n",
+ "259 571500487_01 571510153_02 571545870_01 \n",
+ "295 571500487_01 -571500487_01 571542797_02 \n",
+ "296 571545870_01 -571542797_02 571510153_01 \n",
+ "297 571510153_01 571545870_02 571542797_02 \n",
+ "298 571510153_01 571510153_02 571545870_01 \n",
+ "299 571500487_01 571510153_02 571545870_01 \n",
+ "325 571500487_01 -571500487_01 571542797_02 \n",
+ "326 571545870_01 -571542797_02 571510153_01 \n",
+ "327 571510153_01 571545870_02 571542797_02 \n",
+ "328 571510153_01 571510153_02 571545870_01 \n",
+ "329 571500487_01 571510153_02 571545870_01 \n",
+ "355 571500487_01 -571500487_01 571542797_02 \n",
+ "356 571545870_01 -571542797_02 571510153_01 \n",
+ "357 571510153_01 571545870_02 571542797_02 \n",
+ "358 571510153_01 571510153_02 571545870_01 \n",
+ "359 571500487_01 571510153_02 571545870_01 \n",
+ "400 571500487_01 -571500487_01 571542797_02 \n",
+ "401 571545870_01 -571542797_02 571510153_01 \n",
+ "402 571510153_01 571545870_02 571542797_02 \n",
+ "403 571510153_01 571510153_02 571545870_01 \n",
+ "404 571500487_01 571510153_02 571545870_01 "
+ ]
+ },
+ "execution_count": 69,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "print(datetime.fromtimestamp(present_time))\n",
+ "histid[histid.inter_no==175][:60]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 70,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " start_hour | \n",
+ " start_minute | \n",
+ " dura_A1 | \n",
+ " dura_A2 | \n",
+ " dura_A3 | \n",
+ " dura_A4 | \n",
+ " dura_A5 | \n",
+ " dura_A6 | \n",
+ " dura_A7 | \n",
+ " ... | \n",
+ " dura_B1 | \n",
+ " dura_B2 | \n",
+ " dura_B3 | \n",
+ " dura_B4 | \n",
+ " dura_B5 | \n",
+ " dura_B6 | \n",
+ " dura_B7 | \n",
+ " dura_B8 | \n",
+ " cycle | \n",
+ " offset | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 37 | \n",
+ " 39 | \n",
+ " 55 | \n",
+ " 29 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " ... | \n",
+ " 37 | \n",
+ " 39 | \n",
+ " 25 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ " 57 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " 7 | \n",
+ " 0 | \n",
+ " 40 | \n",
+ " 42 | \n",
+ " 55 | \n",
+ " 33 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " ... | \n",
+ " 40 | \n",
+ " 42 | \n",
+ " 29 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 170 | \n",
+ " 40 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " 9 | \n",
+ " 0 | \n",
+ " 43 | \n",
+ " 45 | \n",
+ " 55 | \n",
+ " 37 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " ... | \n",
+ " 43 | \n",
+ " 45 | \n",
+ " 33 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 180 | \n",
+ " 28 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " 18 | \n",
+ " 30 | \n",
+ " 46 | \n",
+ " 48 | \n",
+ " 55 | \n",
+ " 41 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " ... | \n",
+ " 46 | \n",
+ " 48 | \n",
+ " 37 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 190 | \n",
+ " 18 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
4 rows × 21 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no start_hour start_minute dura_A1 dura_A2 dura_A3 dura_A4 \\\n",
+ "0 175 0 0 37 39 55 29 \n",
+ "1 175 7 0 40 42 55 33 \n",
+ "2 175 9 0 43 45 55 37 \n",
+ "3 175 18 30 46 48 55 41 \n",
+ "\n",
+ " dura_A5 dura_A6 dura_A7 ... dura_B1 dura_B2 dura_B3 dura_B4 \\\n",
+ "0 0 0 0 ... 37 39 25 59 \n",
+ "1 0 0 0 ... 40 42 29 59 \n",
+ "2 0 0 0 ... 43 45 33 59 \n",
+ "3 0 0 0 ... 46 48 37 59 \n",
+ "\n",
+ " dura_B5 dura_B6 dura_B7 dura_B8 cycle offset \n",
+ "0 0 0 0 0 160 57 \n",
+ "1 0 0 0 0 170 40 \n",
+ "2 0 0 0 0 180 28 \n",
+ "3 0 0 0 0 190 18 \n",
+ "\n",
+ "[4 rows x 21 columns]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " end_unix | \n",
+ " dura_A1 | \n",
+ " dura_A2 | \n",
+ " dura_A3 | \n",
+ " dura_A4 | \n",
+ " dura_A5 | \n",
+ " dura_A6 | \n",
+ " dura_A7 | \n",
+ " dura_A8 | \n",
+ " dura_B1 | \n",
+ " dura_B2 | \n",
+ " dura_B3 | \n",
+ " dura_B4 | \n",
+ " dura_B5 | \n",
+ " dura_B6 | \n",
+ " dura_B7 | \n",
+ " dura_B8 | \n",
+ " cycle | \n",
+ " offset | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 6 | \n",
+ " 175 | \n",
+ " 1704380561 | \n",
+ " 37 | \n",
+ " 39 | \n",
+ " 55 | \n",
+ " 29 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 37 | \n",
+ " 39 | \n",
+ " 25 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ " 57 | \n",
+ "
\n",
+ " \n",
+ " 14 | \n",
+ " 175 | \n",
+ " 1704380720 | \n",
+ " 37 | \n",
+ " 39 | \n",
+ " 55 | \n",
+ " 29 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 37 | \n",
+ " 39 | \n",
+ " 25 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ " 57 | \n",
+ "
\n",
+ " \n",
+ " 22 | \n",
+ " 175 | \n",
+ " 1704380881 | \n",
+ " 37 | \n",
+ " 39 | \n",
+ " 55 | \n",
+ " 29 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 37 | \n",
+ " 39 | \n",
+ " 25 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ " 57 | \n",
+ "
\n",
+ " \n",
+ " 31 | \n",
+ " 175 | \n",
+ " 1704381040 | \n",
+ " 37 | \n",
+ " 39 | \n",
+ " 55 | \n",
+ " 29 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 37 | \n",
+ " 39 | \n",
+ " 25 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ " 57 | \n",
+ "
\n",
+ " \n",
+ " 39 | \n",
+ " 175 | \n",
+ " 1704381200 | \n",
+ " 37 | \n",
+ " 39 | \n",
+ " 55 | \n",
+ " 29 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 37 | \n",
+ " 39 | \n",
+ " 25 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 160 | \n",
+ " 57 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 3844 | \n",
+ " 175 | \n",
+ " 1704466010 | \n",
+ " 46 | \n",
+ " 48 | \n",
+ " 55 | \n",
+ " 41 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 46 | \n",
+ " 48 | \n",
+ " 37 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 190 | \n",
+ " 18 | \n",
+ "
\n",
+ " \n",
+ " 3852 | \n",
+ " 175 | \n",
+ " 1704466200 | \n",
+ " 46 | \n",
+ " 48 | \n",
+ " 55 | \n",
+ " 41 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 46 | \n",
+ " 48 | \n",
+ " 37 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 190 | \n",
+ " 18 | \n",
+ "
\n",
+ " \n",
+ " 3860 | \n",
+ " 175 | \n",
+ " 1704466390 | \n",
+ " 46 | \n",
+ " 48 | \n",
+ " 55 | \n",
+ " 41 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 46 | \n",
+ " 48 | \n",
+ " 37 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 190 | \n",
+ " 18 | \n",
+ "
\n",
+ " \n",
+ " 3868 | \n",
+ " 175 | \n",
+ " 1704466580 | \n",
+ " 46 | \n",
+ " 48 | \n",
+ " 55 | \n",
+ " 41 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 46 | \n",
+ " 48 | \n",
+ " 37 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 190 | \n",
+ " 18 | \n",
+ "
\n",
+ " \n",
+ " 3876 | \n",
+ " 175 | \n",
+ " 1704466769 | \n",
+ " 46 | \n",
+ " 48 | \n",
+ " 55 | \n",
+ " 41 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 46 | \n",
+ " 48 | \n",
+ " 37 | \n",
+ " 59 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 0 | \n",
+ " 190 | \n",
+ " 18 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
496 rows × 20 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no end_unix dura_A1 dura_A2 dura_A3 dura_A4 dura_A5 \\\n",
+ "6 175 1704380561 37 39 55 29 0 \n",
+ "14 175 1704380720 37 39 55 29 0 \n",
+ "22 175 1704380881 37 39 55 29 0 \n",
+ "31 175 1704381040 37 39 55 29 0 \n",
+ "39 175 1704381200 37 39 55 29 0 \n",
+ "... ... ... ... ... ... ... ... \n",
+ "3844 175 1704466010 46 48 55 41 0 \n",
+ "3852 175 1704466200 46 48 55 41 0 \n",
+ "3860 175 1704466390 46 48 55 41 0 \n",
+ "3868 175 1704466580 46 48 55 41 0 \n",
+ "3876 175 1704466769 46 48 55 41 0 \n",
+ "\n",
+ " dura_A6 dura_A7 dura_A8 dura_B1 dura_B2 dura_B3 dura_B4 dura_B5 \\\n",
+ "6 0 0 0 37 39 25 59 0 \n",
+ "14 0 0 0 37 39 25 59 0 \n",
+ "22 0 0 0 37 39 25 59 0 \n",
+ "31 0 0 0 37 39 25 59 0 \n",
+ "39 0 0 0 37 39 25 59 0 \n",
+ "... ... ... ... ... ... ... ... ... \n",
+ "3844 0 0 0 46 48 37 59 0 \n",
+ "3852 0 0 0 46 48 37 59 0 \n",
+ "3860 0 0 0 46 48 37 59 0 \n",
+ "3868 0 0 0 46 48 37 59 0 \n",
+ "3876 0 0 0 46 48 37 59 0 \n",
+ "\n",
+ " dura_B6 dura_B7 dura_B8 cycle offset \n",
+ "6 0 0 0 160 57 \n",
+ "14 0 0 0 160 57 \n",
+ "22 0 0 0 160 57 \n",
+ "31 0 0 0 160 57 \n",
+ "39 0 0 0 160 57 \n",
+ "... ... ... ... ... ... \n",
+ "3844 0 0 0 190 18 \n",
+ "3852 0 0 0 190 18 \n",
+ "3860 0 0 0 190 18 \n",
+ "3868 0 0 0 190 18 \n",
+ "3876 0 0 0 190 18 \n",
+ "\n",
+ "[496 rows x 20 columns]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "display(plan[plan.inter_no==175])\n",
+ "display(history[history.inter_no==175])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "for m in range(30, 288):\n",
+ " print(m)\n",
+ " make_histid(m).to_csv(f'../../Data/tables/histids/histids_{fmins[m]}.csv')"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "rts",
+ "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.8.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/Analysis/0109_preprocess/0122_preprocess_9.7.ipynb b/Analysis/0109_preprocess/0122_preprocess_9.7.ipynb
new file mode 100644
index 000000000..b2236f2f2
--- /dev/null
+++ b/Analysis/0109_preprocess/0122_preprocess_9.7.ipynb
@@ -0,0 +1,1459 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "import os\n",
+ "import sumolib\n",
+ "import random\n",
+ "from tqdm import tqdm\n",
+ "from datetime import datetime"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# A. 이동류 매칭"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_match1():\n",
+ " '''\n",
+ " 설명 :\n",
+ " 신호 DB에는 매 초마다 이동류정보가 업데이트 된다. 그리고 이 이동류정보를 매 5초마다 불러와서 사용하게 된다.\n",
+ " '../../Data/tables/moves/'에는 5초마다의 이동류정보가 저장되어 있다.\n",
+ "\n",
+ " return : 통합된 이동류정보\n",
+ " - 모든 inter_no(교차로번호)에 대한 A, B링 현시별 이동류정보\n",
+ " '''\n",
+ " # [이동류번호] 불러오기 (약 1분의 소요시간)\n",
+ " path_moves = '../../Data/tables/moves/'\n",
+ " csv_moves = os.listdir('../../Data/tables/moves/')\n",
+ " moves = [pd.read_csv(path_moves + csv_move, index_col=0) for csv_move in tqdm(csv_moves)]\n",
+ " match1 = pd.concat(moves).drop_duplicates().sort_values(by=['inter_no','phas_A','phas_B']).reset_index(drop=True)\n",
+ " match1.to_csv(path_moves + \"match1.csv\")\n",
+ " return match1"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_match2(match1):\n",
+ " '''\n",
+ " match1을 계층화함.\n",
+ " - match1의 컬럼 : inter_no, phas_A, phas_B, move_A, move_B\n",
+ " - match2의 컬럼 : inter_no, phase_no, ring_type, move_no\n",
+ " '''\n",
+ " # 계층화 (inter_no, phas_A, phas_B, move_A, move_B) -> ('inter_no', 'phase_no', 'ring_type', 'move_no')\n",
+ " matchA = match1[['inter_no', 'phas_A', 'move_A']].copy()\n",
+ " matchA.columns = ['inter_no', 'phase_no', 'move_no']\n",
+ " matchA['ring_type'] = 'A'\n",
+ " matchB = match1[['inter_no', 'phas_B', 'move_B']].copy()\n",
+ " matchB.columns = ['inter_no', 'phase_no', 'move_no']\n",
+ " matchB['ring_type'] = 'B'\n",
+ " match2 = pd.concat([matchA, matchB]).drop_duplicates()\n",
+ " match2 = match2[['inter_no', 'phase_no', 'ring_type', 'move_no']]\n",
+ " match2 = match2.sort_values(by=list(match2.columns))\n",
+ " return match2"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_match3(match2):\n",
+ " '''\n",
+ " 각 movement들에 방향(진입방향, 진출방향)을 매칭시켜 추가함.\n",
+ " - match2의 컬럼 : inter_no, phase_no, ring_type, move_no\n",
+ " - match3의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir\n",
+ "\n",
+ " nema : \n",
+ " - 컬럼 : move_no, inc_dir, out_dir\n",
+ " - 모든 종류의 이동류번호에 대하여 진입방향과 진출방향을 매칭시키는 테이블\n",
+ " - 이동류번호 : 1 ~ 16, 17, 18, 21\n",
+ " - 진입, 진출방향(8방위) : 동, 서, 남, 북, 북동, 북서, 남동, 남서\n",
+ " '''\n",
+ " # nema 정보 불러오기 및 병합\n",
+ " nema = pd.read_csv('../../Data/tables/nema.csv', encoding='cp949')\n",
+ " match3 = pd.merge(match2, nema, how='left', on='move_no').drop_duplicates()\n",
+ " return match3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_match4(match3):\n",
+ " '''\n",
+ " 방위각 정보를 매칭시켜 추가함.\n",
+ " - match3의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir\n",
+ " - match4의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle\n",
+ "\n",
+ " angle_original : \n",
+ " - 컬럼 : inter_no, angle_Aj, angle_Bj (j : 1 ~ 8)\n",
+ " - 모든 종류의 이동류번호에 대하여 진입방향과 진출방향을 매칭시키는 테이블\n",
+ " - 이동류번호 : 1 ~ 16, 17, 18, 21\n",
+ " - 진입, 진출방향(8방위) : 동, 서, 남, 북, 북동, 북서, 남동, 남서\n",
+ " '''\n",
+ "\n",
+ " # 방위각 정보 불러오기\n",
+ " dtype_dict = {f'angle_{alph}{j}':'str' for alph in ['A', 'B'] for j in range(1,9)}\n",
+ " angle_original = pd.read_csv('../../Data/tables/angle.csv', index_col=0, dtype = dtype_dict)\n",
+ "\n",
+ " # 계층화\n",
+ " angle = []\n",
+ " for i, row in angle_original.iterrows():\n",
+ " angle_codes = row[[f'angle_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " new = pd.DataFrame({'inter_no':[row.inter_no] * 16, 'phase_no':list(range(1, 9))*2, 'ring_type':['A'] * 8 + ['B'] * 8, 'angle_code':angle_codes.to_list()})\n",
+ " angle.append(new)\n",
+ " angle = pd.concat(angle)\n",
+ " angle = angle.dropna().reset_index(drop=True)\n",
+ "\n",
+ " # 병합\n",
+ " six_chars = angle.angle_code.apply(lambda x:len(x)==6)\n",
+ " angle.loc[six_chars,'inc_angle'] = angle.angle_code.apply(lambda x:x[:3])\n",
+ " angle.loc[six_chars,'out_angle'] = angle.angle_code.apply(lambda x:x[3:])\n",
+ " angle = angle.drop('angle_code', axis=1)\n",
+ " match4 = pd.merge(match3, angle, how='left', left_on=['inter_no', 'phase_no', 'ring_type'],\n",
+ " right_on=['inter_no', 'phase_no', 'ring_type']).drop_duplicates()\n",
+ " return match4"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_match5(match4):\n",
+ " '''\n",
+ " 진입엣지id, 진출엣지id, 노드id를 추가함 (주교차로).\n",
+ " - match4의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle\n",
+ " - match5의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle, inc_edge, out_edge, node_id\n",
+ " \n",
+ " 사용된 데이터 : \n",
+ " (1) net\n",
+ " - 성남시 정자동 부근의 샘플 네트워크\n",
+ " (2) inter_node\n",
+ " - 교차로번호와 노드id를 매칭시키는 테이블.\n",
+ " - parent/child 정보도 포함되어 있음\n",
+ " - 컬럼 : inter_no, node_id, inter_type\n",
+ " (3) inter_info\n",
+ " - 교차로 정보. 여기에서는 위도와 경도가 쓰임.\n",
+ " - 컬럼 : inter_no, inter_name, inter_lat, inter_lon, group_no, main_phase_no\n",
+ "\n",
+ " 진입엣지id, 진출엣지id를 얻는 과정 :\n",
+ " - match5 = match4.copy()의 각 열을 순회하면서 아래 과정을 반복함.\n",
+ " * 진입에 대해서만 서술하겠지만 진출도 마찬가지로 설명될 수 있음\n",
+ " - 해당 행의 교차로정보로부터 노드ID를 얻어내고, 해당 노드에 대한 모든 진출엣지id를 inc_edges에 저장.\n",
+ " * inc_edge(진입엣지) : incoming edge, out_edge(진출엣지) : outgoing_edge\n",
+ " - inc_edges의 모든 진입엣지에 대하여 진입방향(inc_dires, 2차원 단위벡터)을 얻어냄.\n",
+ " - 해당 행의 진입각으로부터 그에 대응되는 진입각방향(단위벡터)를 얻어냄.\n",
+ " - 주어진 진입각방향에 대하여 내적이 가장 작은 진입방향에 대한 진입엣지를 inc_edge_id로 지정함.\n",
+ " '''\n",
+ "\n",
+ " # 네트워크 불러오기 \n",
+ " net = sumolib.net.readNet('../../Data/networks/SN_sample.net.xml')\n",
+ " # 교차로-노드 매칭 정보 불러오기\n",
+ " inter_node = pd.read_csv('../../Data/tables/inter_node.csv', index_col=0)\n",
+ " # 교차로정보(위, 경도) 불러오기\n",
+ " inter_info = pd.read_csv('../../Data/tables/inter_info.csv', index_col=0)\n",
+ "\n",
+ " # parent node만 가져옴.\n",
+ " inter_node1 = inter_node[inter_node.inter_type == 'parent'].drop('inter_type', axis=1)\n",
+ " inter_info1 = inter_info[['inter_no', 'inter_lat', 'inter_lon']]\n",
+ " inter = pd.merge(inter_node1, inter_info1, how='left', left_on=['inter_no'],\n",
+ " right_on=['inter_no']).drop_duplicates()\n",
+ "\n",
+ " inter2node = dict(zip(inter['inter_no'], inter['node_id']))\n",
+ "\n",
+ " match5 = match4.copy()\n",
+ " # 진입진출ID 매칭\n",
+ " for index, row in match5.iterrows():\n",
+ " node_id = inter2node[row.inter_no]\n",
+ " node = net.getNode(node_id)\n",
+ " # 교차로의 모든 (from / to) edges\n",
+ " inc_edges = [edge for edge in node.getIncoming() if edge.getFunction() == ''] # incoming edges\n",
+ " out_edges = [edge for edge in node.getOutgoing() if edge.getFunction() == ''] # outgoing edges\n",
+ " # 교차로의 모든 (from / to) directions\n",
+ " inc_dirs = []\n",
+ " for inc_edge in inc_edges:\n",
+ " start = inc_edge.getShape()[-2]\n",
+ " end = inc_edge.getShape()[-1]\n",
+ " inc_dir = np.array(end) - np.array(start)\n",
+ " inc_dir = inc_dir / (inc_dir ** 2).sum() ** 0.5\n",
+ " inc_dirs.append(inc_dir)\n",
+ " out_dirs = []\n",
+ " for out_edge in out_edges:\n",
+ " start = out_edge.getShape()[0]\n",
+ " end = out_edge.getShape()[1]\n",
+ " out_dir = np.array(end) - np.array(start)\n",
+ " out_dir = out_dir / (out_dir ** 2).sum() ** 0.5\n",
+ " out_dirs.append(out_dir)\n",
+ " # 진입각, 진출각 불러오기\n",
+ " if not pd.isna(row.inc_angle):\n",
+ " inc_angle = int(row.inc_angle)\n",
+ " out_angle = int(row.out_angle)\n",
+ " # 방위각을 일반각으로 가공, 라디안 변환, 단위벡터로 변환\n",
+ " inc_angle = (-90 - inc_angle) % 360\n",
+ " inc_angle = inc_angle * np.pi / 180.\n",
+ " inc_dir_true = np.array([np.cos(inc_angle), np.sin(inc_angle)])\n",
+ " out_angle = (90 - out_angle) % 360\n",
+ " out_angle = out_angle * np.pi / 180.\n",
+ " out_dir_true = np.array([np.cos(out_angle), np.sin(out_angle)])\n",
+ " # 매칭 엣지 반환\n",
+ " inc_index = np.array([np.dot(inc_dir, inc_dir_true) for inc_dir in inc_dirs]).argmax()\n",
+ " out_index = np.array([np.dot(out_dir, out_dir_true) for out_dir in out_dirs]).argmax()\n",
+ " inc_edge_id = inc_edges[inc_index].getID()\n",
+ " out_edge_id = out_edges[out_index].getID()\n",
+ " match5.at[index, 'inc_edge'] = inc_edge_id\n",
+ " match5.at[index, 'out_edge'] = out_edge_id\n",
+ " match5['node_id'] = match5['inter_no'].map(inter2node)\n",
+ " match5 = match5.sort_values(by=['inter_no','phase_no','ring_type']).reset_index(drop=True)\n",
+ " return match5"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_match6(match5):\n",
+ " '''\n",
+ " 진입엣지id, 진출엣지id, 노드id를 추가함 (부교차로).\n",
+ " - match6의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle, inc_edge, out_edge, node_id\n",
+ " \n",
+ " 사용된 데이터 : \n",
+ " (1) inter_node\n",
+ " - 교차로번호와 노드id를 매칭시키는 테이블.\n",
+ " - parent/child 정보도 포함되어 있음\n",
+ " - 컬럼 : inter_no, node_id, inter_type\n",
+ " (2) uturn (유턴정보)\n",
+ " - 컬럼 : parent_id, child_id, direction, condition, inc_edge, out_edge\n",
+ " - parent_id, child_id : 주교차로id, 유턴교차로id\n",
+ " - direction : 주교차로에 대한 유턴노드의 상대적인 위치(방향)\n",
+ " - condition : 좌회전시, 직진시, 직좌시, 보행신호시 중 하나\n",
+ " - inc_edge, out_edge : 유턴에 대한 진입진출엣지\n",
+ " (3) coord (연동교차로정보)\n",
+ " - 컬럼 : parent_id, child_id, phase_no, ring_type, inc_edge, out_edge\n",
+ " - parent_id, child_id : 주교차로id, 연동교차로id\n",
+ " - 나머지 컬럼 : 각 (현시, 링)별 진입진출엣지\n",
+ "\n",
+ " 설명 :\n",
+ " - match5는 주교차로에 대해서만 진입엣지id, 진출엣지id, 노드id를 추가했었음.\n",
+ " 여기에서 uturn, coord를 사용해서 부교차로들(유턴교차로, 연동교차로)에 대해서도 해당 값들을 부여함.\n",
+ " 유턴교차로 :\n",
+ " - directions를 정북기준 시계방향의 8방위로 정함.\n",
+ " - 이를 통해 진입방향이 주어진 경우에 좌회전, 직진, 보행 등에 대한 (진입방향, 진출방향)을 얻어낼 수 있음.\n",
+ " - 예) 진입방향(direction)이 '북'일 때, \n",
+ " - 직진 : (북, 남)\n",
+ " * 남 : directions[(ind + 4) % len(directions)]\n",
+ " - 좌회전 : (북, 동)\n",
+ " * 동 : directions[(ind + 2) % len(directions)]\n",
+ " - 보행 : (서, 동)\n",
+ " * 서 : directions[(ind - 2) % len(directions)]\n",
+ " - uturn의 각 행을 순회하면서 아래 과정을 반복함\n",
+ " - match5에서 parent_id에 해당하는 행들을 가져옴(cmatch).\n",
+ " - condition 별로 진입방향, 진출방향A, 진출방향B 정함.\n",
+ " - 상술한 directions를 활용하여 정함.\n",
+ " - (진입방향, 진출방향A, 진출방향B)을 고려하여 (현시, 링) 별로 진입엣지id, 진출엣지id를 정함.\n",
+ " - ex) cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " - 순회하면서 만든 cmatch를 cmatchs라는 리스트에 저장함.\n",
+ "\n",
+ " 연동교차로 :\n",
+ " - 연동교차로의 경우 coord에 (현시, 링)별 진입엣지ID, 진출엣지ID가 명시되어 있음.\n",
+ " - 'inc_dir', 'out_dir', 'inc_angle','out_angle'와 같은 열들은 np.nan을 지정해놓음.\n",
+ " - 이 열들은, 사실상 다음 스텝부터는 사용되지 않는 열들이기 때문에 np.nan으로 지정해놓아도 문제없음.\n",
+ "\n",
+ " match6 :\n",
+ " - 이렇게 얻은 match5, cmatchs, coord를 모두 pd.concat하여 match6을 얻어냄.\n",
+ " '''\n",
+ "\n",
+ " inter_node = pd.read_csv('../../Data/tables/inter_node.csv', index_col=0)\n",
+ " node2inter = dict(zip(inter_node['node_id'], inter_node['inter_no']))\n",
+ "\n",
+ " uturn = pd.read_csv('../../Data/tables/child_uturn.csv')\n",
+ " coord = pd.read_csv('../../Data/tables/child_coord.csv')\n",
+ " child_ids = inter_node[inter_node.inter_type=='child'].node_id.unique()\n",
+ " ch2pa = {} # child to parent\n",
+ " for child_id in child_ids:\n",
+ " parent_no = inter_node[inter_node.node_id==child_id].inter_no.iloc[0]\n",
+ " sub_inter_node = inter_node[inter_node.inter_no==parent_no]\n",
+ " ch2pa[child_id] = sub_inter_node[sub_inter_node.inter_type=='parent'].iloc[0].node_id\n",
+ " directions = ['북', '북동', '동', '남동', '남', '남서', '서', '북서'] # 정북기준 시계방향으로 8방향\n",
+ "\n",
+ " # 각 uturn node에 대하여 (inc_edge_id, out_edge_id) 부여\n",
+ " cmatches = []\n",
+ " for _, row in uturn.iterrows():\n",
+ " child_id = row.child_id\n",
+ " parent_id = row.parent_id\n",
+ " direction = row.direction\n",
+ " condition = row.condition\n",
+ " inc_edge_id = row.inc_edge\n",
+ " out_edge_id = row.out_edge\n",
+ " # match5에서 parent_id에 해당하는 행들을 가져옴\n",
+ " cmatch = match5.copy()[match5.node_id==parent_id] # match dataframe for a child node\n",
+ " cmatch = cmatch.sort_values(by=['phase_no', 'ring_type']).reset_index(drop=True)\n",
+ " cmatch['node_id'] = child_id\n",
+ " cmatch[['inc_edge', 'out_edge']] = np.nan\n",
+ "\n",
+ " # condition 별로 inc_dire, out_dire_A, out_dire_B를 정함\n",
+ " ind = directions.index(direction)\n",
+ " if condition == \"좌회전시\":\n",
+ " inc_dire = direction\n",
+ " out_dire_A = out_dire_B = directions[(ind + 2) % len(directions)]\n",
+ " elif condition == \"직진시\":\n",
+ " inc_dire = direction\n",
+ " out_dire_A = out_dire_B = directions[(ind + 4) % len(directions)]\n",
+ " elif condition == \"직좌시\":\n",
+ " inc_dire = direction\n",
+ " out_dire_A = directions[(ind + 2) % len(directions)]\n",
+ " out_dire_B = directions[(ind + 4) % len(directions)]\n",
+ " elif condition == \"보행신호시\":\n",
+ " inc_dire = directions[(ind + 2) % len(directions)]\n",
+ " out_dire_A = directions[(ind - 2) % len(directions)]\n",
+ " out_dire_B = directions[(ind - 2) % len(directions)]\n",
+ "\n",
+ " # (inc_dire, out_dire_A, out_dire_B) 별로 inc_edge_id, out_edge_id를 정함\n",
+ " if condition == '직좌시':\n",
+ " ap = cmatch[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A)].phase_no.iloc[0]\n",
+ " bp = cmatch[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B)].phase_no.iloc[0]\n",
+ " # 직진과 좌회전이 같은 현시에 있는 경우에만 (inc_edge_id, out_edge_id)를 부여한다.\n",
+ " if ap == bp:\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " elif condition == '보행신호시':\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " # 이동류번호가 17(보행신호)이면서 유턴노드방향으로 가는 신호가 없으면 (inc_edge_id, out_edge_id)를 부여한다.\n",
+ " cmatch.loc[(cmatch.move_no==17) & (cmatch.out_dir!=direction), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " else: # '직진시', '좌회전시'\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " # 유턴신호의 이동류번호를 19로 부여한다.\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), 'move_no'] = 19\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), 'move_no'] = 19\n",
+ " cmatches.append(cmatch)\n",
+ "\n",
+ " # 각 coordination node에 대하여 (inc_edge_id, out_edge_id) 부여\n",
+ " coord['inter_no'] = coord['parent_id'].map(node2inter)\n",
+ " coord = coord.rename(columns={'child_id':'node_id'})\n",
+ " coord[['inc_dir', 'out_dir', 'inc_angle','out_angle']] = np.nan\n",
+ " coord['move_no'] = 20\n",
+ " coord = coord[['inter_no', 'phase_no', 'ring_type', 'move_no', 'inc_dir', 'out_dir', 'inc_angle','out_angle', 'inc_edge', 'out_edge', 'node_id']]\n",
+ " \n",
+ " # display(coord)\n",
+ " cmatches = pd.concat(cmatches)\n",
+ " match6 = pd.concat([match5, cmatches, coord]).drop_duplicates().sort_values(by=['inter_no', 'node_id', 'phase_no', 'ring_type'])\n",
+ " # with pd.option_context('display.max_rows', None, 'display.max_columns', None):\n",
+ " match6.to_csv('../../Data/tables/matching/match6.csv')\n",
+ " return match6"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_matching(match6):\n",
+ " '''\n",
+ " 이동류 매칭 : 각 교차로에 대하여, 가능한 모든 이동류 (1~18, 21)에 대한 진입·진출엣지ID를 지정한다.\n",
+ " 모든 이동류에 대해 지정하므로, 시차제시 이전과 다른 이동류가 등장하더라도 항상 진입·진출 엣지 ID를 지정할 수 있다. \n",
+ " - matching의 컬럼 : inter_no, move_no, inc_dir, out_dir, inc_edge, out_edge, node_id\n",
+ " \n",
+ " 설명 : \n",
+ " - 필요한 리스트, 딕셔너리 등을 정의\n",
+ " (1) 가능한 (진입방향, 진출방향) 목록 [리스트]\n",
+ " (2) 각 교차로별 방향 목록 : pdires (possible directions) [딕셔너리]\n",
+ " (3) 각 (교차로, 진입방향) 별 진입id 목록 : inc2id (incoming direction to incoming edge_id) [딕셔너리]\n",
+ " (4) 각 (교차로, 진출방향) 별 진출id 목록 : out2id (outgoing direction to outgoing edge_id) [딕셔너리]\n",
+ " (5) 각 교차로별 가능한 (진입방향, 진출방향) 목록 : pflow (possible flows) [딕셔너리]\n",
+ " - matching은 빈 리스트로 지정.\n",
+ " - 모든 노드id에 대하여 다음 과정을 반복\n",
+ " - 해당 노드id에 대한 모든 가능한 (진입방향, 진출방향)에 대하여 다음 과정을 반복\n",
+ " - (노드id, 진입방향)으로부터 진입엣지id를 얻어냄. 마찬가지로 진출엣지id도 얻어냄\n",
+ " - 얻어낸 정보를 바탕으로 한 행(new_row)을 만들고 이것을 matching에 append\n",
+ " '''\n",
+ "\n",
+ " match7 = match6.copy()\n",
+ " match7 = match7[['inter_no', 'move_no', 'inc_dir', 'out_dir', 'inc_edge', 'out_edge', 'node_id']]\n",
+ " inter_node = pd.read_csv('../../Data/tables/inter_node.csv', index_col=0)\n",
+ " nema = pd.read_csv('../../Data/tables/nema.csv', encoding='cp949')\n",
+ "\n",
+ " parent_ids = sorted(inter_node[inter_node.inter_type=='parent'].node_id.unique())\n",
+ " child_ids = sorted(inter_node[inter_node.inter_type=='child'].node_id.unique())\n",
+ "\n",
+ " # (1) 가능한 (진입방향, 진출방향) 목록 \n",
+ " flows = nema.dropna().apply(lambda row: (row['inc_dir'], row['out_dir']), axis=1).tolist()\n",
+ " # (2) 각 교차로별 방향 목록 : pdires (possible directions)\n",
+ " pdires = {}\n",
+ " for node_id in parent_ids:\n",
+ " dires = match7[match7.node_id == node_id][['inc_dir','out_dir']].values.flatten()\n",
+ " dires = {dire for dire in dires if type(dire)==str}\n",
+ " pdires[node_id] = dires\n",
+ " # (3) 각 (교차로, 진입방향) 별 진입id 목록 : inc2id (incoming direction to incoming edge_id)\n",
+ " inc2id = {}\n",
+ " for node_id in parent_ids:\n",
+ " for inc_dir in pdires[node_id]:\n",
+ " df = match7[(match7.node_id==node_id) & (match7.inc_dir==inc_dir)]\n",
+ " inc2id[(node_id, inc_dir)] = df.inc_edge.iloc[0]\n",
+ " # (4) 각 (교차로, 진출방향) 별 진출id 목록 : out2id (outgoing direction to outgoing edge_id)\n",
+ " out2id = {}\n",
+ " for node_id in parent_ids:\n",
+ " for out_dir in pdires[node_id]:\n",
+ " df = match7[(match7.node_id==node_id) & (match7.out_dir==out_dir)]\n",
+ " out2id[(node_id, out_dir)] = df.out_edge.iloc[0]\n",
+ " # (5) 각 교차로별 가능한 (진입방향, 진출방향) 목록 : pflow (possible flows)\n",
+ " pflow = {}\n",
+ " for node_id in parent_ids:\n",
+ " pflow[node_id] = [flow for flow in flows if set(flow).issubset(pdires[node_id])]\n",
+ " # (6) 가능한 이동류에 대하여 진입id, 진출id 배정 : matching\n",
+ " node2inter = dict(zip(match7['node_id'], match7['inter_no']))\n",
+ " dires_right = ['북', '서', '남', '동', '북'] # ex (북, 서), (서, 남) 등은 우회전 flow\n",
+ " matching = []\n",
+ " for node_id in parent_ids:\n",
+ " inter_no = node2inter[node_id]\n",
+ " # 좌회전과 직진(1 ~ 16)\n",
+ " for (inc_dir, out_dir) in pflow[node_id]:\n",
+ " move_no = nema[(nema.inc_dir==inc_dir) & (nema.out_dir==out_dir)].move_no.iloc[0]\n",
+ " inc_edge = inc2id[(node_id, inc_dir)]\n",
+ " out_edge = out2id[(node_id, out_dir)]\n",
+ " new_row = pd.DataFrame({'inter_no':[inter_no], 'move_no':[move_no],\n",
+ " 'inc_dir':[inc_dir], 'out_dir':[out_dir],\n",
+ " 'inc_edge':[inc_edge], 'out_edge':[out_edge], 'node_id':[node_id]})\n",
+ " matching.append(new_row)\n",
+ " # 보행신호(17), 전적색(18)\n",
+ " new_row = pd.DataFrame({'inter_no':[inter_no] * 2, 'move_no':[17, 18],\n",
+ " 'inc_dir':[None]*2, 'out_dir':[None]*2,\n",
+ " 'inc_edge':[None]*2, 'out_edge':[None]*2, 'node_id':[node_id]*2})\n",
+ " matching.append(new_row)\n",
+ " # 신호우회전(21)\n",
+ " for d in range(len(dires_right)-1):\n",
+ " inc_dir = dires_right[d]\n",
+ " out_dir = dires_right[d+1]\n",
+ " if {inc_dir, out_dir}.issubset(pdires[node_id]):\n",
+ " inc_edge = inc2id[(node_id, inc_dir)]\n",
+ " out_edge = out2id[(node_id, out_dir)]\n",
+ " new_row = pd.DataFrame({'inter_no':[inter_no], 'move_no':[21],\n",
+ " 'inc_dir':[inc_dir], 'out_dir':[out_dir],\n",
+ " 'inc_edge':[inc_edge], 'out_edge':[out_edge], 'node_id':[node_id]})\n",
+ " matching.append(new_row)\n",
+ " matching.append(match7[match7.node_id.isin(child_ids)])\n",
+ " matching = pd.concat(matching)\n",
+ " matching = matching.dropna().sort_values(by=['inter_no', 'node_id', 'move_no']).reset_index(drop=True)\n",
+ " matching['move_no'] = matching['move_no'].astype(int)\n",
+ " matching.to_csv('../../Data/tables/matching/matching.csv')\n",
+ " return matching"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def matching_main():\n",
+ " match1 = pd.read_csv('../../Data/tables/moves/match1.csv', index_col=0)\n",
+ " match2 = make_match2(match1)\n",
+ " match3 = make_match3(match2)\n",
+ " match4 = make_match4(match3)\n",
+ " match5 = make_match5(match4)\n",
+ " match6 = make_match6(match5)\n",
+ " matching = make_matching(match6)\n",
+ " return matching\n",
+ "matching = matching_main()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# B. 5초 간격으로 이동류번호 수집"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 5초 단위로 이동류번호 저장 및 신호이력에서 유닉스시각 가져와서 표시, 한시간동안의 데이터만 보관\n",
+ "midnight = int(datetime(2024, 1, 5, 0, 0, 0).timestamp())\n",
+ "next_day = int(datetime(2024, 1, 6, 0, 0, 0).timestamp())\n",
+ "fsecs = range(midnight, next_day, 5) # fsecs : unix time by Five SECondS\n",
+ "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def save_movement():\n",
+ " # time2move = dict(zip(fsecs,moves)) # move : 어느 순간의 이동류정보\n",
+ " history = pd.read_csv('../../Data/tables/history.csv', index_col=0)\n",
+ "\n",
+ " time2movement = {} # movement : 어느 순간의, 그 순간으로부터 한시간 동안의 (교차로번호 + 현시별이동류번호 + 시작시간)\n",
+ " # - 아래 절차를 5초마다 반복\n",
+ " for fsec in tqdm(fsecs): # fsec : unix time by Five SECond\n",
+ " # 1. 상태 테이블 조회해서 전체 데이터중 필요데이터(교차로번호, A링 현시번호, A링 이동류번호, B링 현시번호, B링 이동류번호)만 수집 : A\n",
+ " # move = time2move[fsec]\n",
+ " move = pd.read_csv(f'../../Data/tables/moves/move_{fsec}.csv', index_col=0)\n",
+ " # 2. 이력 테이블 조회해서 교차로별로 유닉스시간 최대인 데이터(교차로변호, 종료유닉스타임)만 수집 : B\n",
+ " recent_histories = [group.iloc[-1:] for _, group in history[history['end_unix'] < fsec].groupby('inter_no')] # 교차로별로 유닉스시간이 최대인 행들\n",
+ " if not recent_histories:\n",
+ " rhistory = pd.DataFrame({'inter_no':[], 'end_unix':[]}) # recent history\n",
+ " else:\n",
+ " rhistory = pd.concat(recent_histories)\n",
+ " recent_unix = rhistory[['inter_no', 'end_unix']]\n",
+ " # 3. 상태 테이블 조회정보(A)와 이력 테이블 조회정보(B) 조인(키값 : 교차로번호) : C\n",
+ " move = pd.merge(move, recent_unix, how='left', on='inter_no')\n",
+ " move['end_unix'] = move['end_unix'].fillna(0).astype(int)\n",
+ " move = move.drop_duplicates()\n",
+ " # 4. C데이터 프레임에 신규 컬럼(시작 유닉스타임) 생성 후 종료유닉스 타임 값 입력, 종료 유닉스 타임 컬럼 제거\n",
+ " move = move.rename(columns = {'end_unix':'start_unix'})\n",
+ " # 5. 이동류 이력정보 READ\n",
+ " # - CSV 파일로 서버에 저장된 이동류정보를 읽어옴(파일이 없는 경우에는 데이터가 없는 프레임 D 생성)\n",
+ " try:\n",
+ " if isinstance(movement, pd.DataFrame): # movement가 존재할 경우 그걸 그대로 씀.\n",
+ " pass\n",
+ " else: \n",
+ " movement = pd.DataFrame()\n",
+ " except NameError: # movement가 존재하지 않는 경우 생성\n",
+ " movement = pd.DataFrame()\n",
+ " # 6. 이동류 이력정보 데이터테이블(D)에 C데이터 add\n",
+ " movement = pd.concat([movement, move])\n",
+ " # 7. D데이터 프레임에서 중복데이터 제거(교차로번호, 시작 유닉스타임, A링 현시번호, B링 현시번호 같은 행은 제거)\n",
+ " movement = movement.drop_duplicates(['inter_no','phas_A','phas_B','start_unix'])\n",
+ " # 8. D데이터 보관 시간 기준시간을 시작 유닉스 타임의 최대값 - 3600을 값으로 산출하고, 보관 시간 기준시간보다 작은 시작 유닉스 타임을 가진 행은 모두 제거(1시간 데이터만 보관)\n",
+ " movement = movement[movement.start_unix > fsec - 3600]\n",
+ " movement = movement.sort_values(by=['start_unix','inter_no','phas_A','phas_B']).reset_index(drop=True)\n",
+ "\n",
+ " time2movement[fsec] = movement\n",
+ " movement.to_csv(f'../../Data/tables/movements/movements_{fsec}.csv')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# C. 5분 간격으로 신호이력 수집 및 통합테이블 생성"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "midnight = int(datetime(2024, 1, 5, 0, 0, 0).timestamp())\n",
+ "next_day = int(datetime(2024, 1, 6, 0, 0, 0).timestamp())\n",
+ "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_splits(plan):\n",
+ " # split, isplit : A,B 분리 혹은 통합시 사용될 수 있는 딕셔너리 \n",
+ " splits = {} # splits maps (inter_no, start_hour, start_minute) to split \n",
+ " for i, row in plan.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_hour = row.start_hour\n",
+ " start_minute = row.start_minute\n",
+ " cycle = row.cycle\n",
+ " cums_A = row[[f'dura_A{j}' for j in range(1,9)]].cumsum()\n",
+ " cums_B = row[[f'dura_B{j}' for j in range(1,9)]].cumsum()\n",
+ " splits[(inter_no, start_hour, start_minute)] = {} # split maps (phas_A, phas_B) to k\n",
+ " k = 0\n",
+ " for t in range(cycle):\n",
+ " new_phas_A = len(cums_A[cums_A < t]) + 1\n",
+ " new_phas_B = len(cums_B[cums_B < t]) + 1\n",
+ " if k == 0 or ((new_phas_A, new_phas_B) != (phas_A, phas_B)):\n",
+ " k += 1\n",
+ " phas_A = new_phas_A\n",
+ " phas_B = new_phas_B\n",
+ " splits[(inter_no, start_hour, start_minute)][(phas_A, phas_B)] = k\n",
+ "\n",
+ " isplits = {} # the inverse of splits\n",
+ " for i in splits:\n",
+ " isplits[i] = {splits[i][k]:k for k in splits[i]} # isplit maps k to (phas_A, phas_B)\n",
+ " return splits, isplits\n",
+ "\n",
+ "def make_timetable(plan):\n",
+ " # timetable\n",
+ " timetable = plan[['start_hour', 'start_minute']].drop_duplicates()\n",
+ " timetable['start_seconds'] = midnight + timetable['start_hour'] * 3600 + timetable['start_minute'] * 60\n",
+ " return timetable\n",
+ "\n",
+ "# inter2node\n",
+ "inter_node = pd.read_csv('../../Data/tables/inter_node.csv', index_col=0)\n",
+ "inter2node = dict(zip(inter_node['inter_no'], inter_node['node_id']))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_rhists(present_time, timetable, plan, history):\n",
+ " # 1. 조회시점의 유닉스 타임 이전의 신호이력 수집\n",
+ " rhistory = history.copy() # recent history\n",
+ " rhistory = rhistory[(rhistory.end_unix < present_time)]\n",
+ " # 2. 시작 유닉스 타임컬럼 생성 후 종류 유닉스 타임에서 현시별 현시기간 컬럼의 합을 뺀 값으로 입력\n",
+ " # - 현시시간의 합을 뺀 시간의 +- 10초 이내에 이전 주기정보가 존재하면 그 유닉스 시간을 시작 유닉스시간 값으로 하고, 존재하지 않으면 현시시간의 합을 뺀 유닉스 시간을 시작 유닉스 시간으로 지정\n",
+ " for i, row in rhistory.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " end_unix = row.end_unix\n",
+ " elapsed_time = row[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]].sum() // 2 # 현시시간 합\n",
+ " # 이전 유닉스 존재하지 않음 : 현시시간 합의 차\n",
+ " start_unix = end_unix - elapsed_time\n",
+ " pre_rows = history[:i] # previous rows\n",
+ " if inter_no in pre_rows.inter_no.unique(): # 이전 유닉스 존재\n",
+ " pre_unix = pre_rows[pre_rows.inter_no == inter_no]['end_unix'].iloc[-1] # previous unix time\n",
+ " # 이전 유닉스 존재, abs < 10 : 이전 유닉스\n",
+ " if abs(pre_unix - start_unix) < 10:\n",
+ " start_unix = pre_unix\n",
+ " # 이전 유닉스 존재, abs >=10 : 현시시간 합의 차\n",
+ " else:\n",
+ " pass\n",
+ " rhistory.loc[i, 'start_unix'] = start_unix \n",
+ " rhistory[rhistory.isna()] = 0\n",
+ " rhistory['start_unix'] = rhistory['start_unix'].astype(int)\n",
+ " rhistory[['inter_no', 'start_unix', 'cycle']][rhistory.inter_no==175]\n",
+ " rhistory = rhistory[['inter_no', 'start_unix'] + [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)] + ['cycle']]\n",
+ "\n",
+ " # 2-1. 참값 판단 프로세스\n",
+ " hours = np.array(range(midnight, next_day + 1, 3600)) # 정각에 해당하는 시각들 목록\n",
+ "\n",
+ " def calculate_DS(rhist, curr_unix):\n",
+ " ghour_lt_curr_unix = hours[hours <= curr_unix].max() # the greatest hour less than (or equal to) curr_unix\n",
+ " start_unixes = rhist.start_unix.unique()\n",
+ " start_unixes_lt_ghour = np.sort(start_unixes[start_unixes < ghour_lt_curr_unix]) # start unixes less than ghour_lt_curr_unix\n",
+ " # 기준유닉스(base_unix) : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 start_unix\n",
+ " if list(start_unixes_lt_ghour):\n",
+ " base_unix = start_unixes_lt_ghour[-5]\n",
+ " # start_unixes_lt_ghour가 비었을 경우에는 맨 앞 start_unix로 base_unix를 지정\n",
+ " else:\n",
+ " base_unix = rhist.start_unix.min()\n",
+ " D_n = curr_unix - base_unix\n",
+ " S_n_durs = rhist[(rhist.start_unix > base_unix) & (rhist.start_unix <= curr_unix)] \\\n",
+ " [[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " S_n = S_n_durs.values.sum() // 2\n",
+ " return D_n, S_n\n",
+ "\n",
+ " rhists = []\n",
+ " for inter_no in sorted(rhistory.inter_no.unique()):\n",
+ " rhist = rhistory.copy()[rhistory.inter_no==inter_no]\n",
+ " rhist = rhist.drop_duplicates(subset=['start_unix']).reset_index(drop=True)\n",
+ "\n",
+ " # D_n 및 S_n 값 정의\n",
+ " rhist['D_n'] = 0 # D_n : 시간차이\n",
+ " rhist['S_n'] = 0 # S_n : 현시시간합\n",
+ " for n in range(len(rhist)):\n",
+ " curr_unix = rhist.iloc[n].start_unix # current start_unix\n",
+ " rhist.loc[n, ['D_n', 'S_n']] = calculate_DS(rhist, curr_unix)\n",
+ "\n",
+ " # 이전시각, 현재시각\n",
+ " prev_unix = rhist.loc[0, 'start_unix'] # previous start_unix\n",
+ " curr_unix = rhist.loc[1, 'start_unix'] # current start_unix\n",
+ "\n",
+ " # rhist의 마지막 행에 도달할 때까지 반복\n",
+ " while True:\n",
+ " n = rhist[rhist.start_unix==curr_unix].index[0]\n",
+ " cycle = rhist.loc[n, 'cycle']\n",
+ " D_n = rhist.loc[n, 'D_n']\n",
+ " S_n = rhist.loc[n, 'S_n']\n",
+ " # 참값인 경우\n",
+ " if (abs(D_n - S_n) <= 5):\n",
+ " pass\n",
+ " # 참값이 아닌 경우\n",
+ " else:\n",
+ " # 2-1-1. 결측치 처리 : 인접한 두 start_unix의 차이가 계획된 주기의 두 배보다 크면 결측이 일어났다고 판단, 신호계획의 현시시간으로 \"대체\"\n",
+ " if curr_unix - prev_unix >= 2 * cycle:\n",
+ " # prev_unix를 계획된 주기만큼 늘려가면서 한 행씩 채워나간다.\n",
+ " # (curr_unix와의 차이가 계획된 주기보다 작거나 같아질 때까지)\n",
+ " new_rows = []\n",
+ " while curr_unix - prev_unix > cycle:\n",
+ " prev_unix += cycle\n",
+ " # 신호 계획(prow) 불러오기\n",
+ " start_seconds = np.array(timetable.start_seconds)\n",
+ " idx = (start_seconds <= prev_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[idx].start_hour\n",
+ " start_minute = timetable.iloc[idx].start_minute\n",
+ " prow = plan.copy()[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
+ " # prow에서 필요한 부분을 rhist에 추가\n",
+ " prow['start_unix'] = prev_unix\n",
+ " prow = prow.drop(['start_hour', 'start_minute', 'offset'], axis=1)\n",
+ " cycle = prow.iloc[0].cycle\n",
+ " rhist = pd.concat([rhist, prow])\n",
+ " rhist = rhist.sort_values(by='start_unix').reset_index(drop=True)\n",
+ " n += 1\n",
+ "\n",
+ " # 2-1-2. 이상치 처리 : 비율에 따라 해당 행을 \"삭제\"(R_n <= 0.5) 또는 \"조정\"(R_n > 0.5)한다\n",
+ " R_n = (curr_unix - prev_unix) / cycle # R_n : 비율\n",
+ " # R_n이 0.5보다 작거나 같으면 해당 행을 삭제\n",
+ " if R_n <= 0.5:\n",
+ " rhist = rhist.drop(index=n).reset_index(drop=True)\n",
+ " # 행삭제에 따른 curr_unix, R_n 재정의\n",
+ " curr_unix = rhist.loc[n, 'start_unix']\n",
+ " R_n = (curr_unix - prev_unix) / cycle # R_n : 비율\n",
+ "\n",
+ " # R_n이 0.5보다 크면 해당 행 조정 (비율을 유지한 채로 현시시간 대체)\n",
+ " if R_n > 0.5:\n",
+ " # 신호 계획(prow) 불러오기\n",
+ " start_seconds = np.array(timetable.start_seconds)\n",
+ " idx = (start_seconds <= curr_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[idx].start_hour\n",
+ " start_minute = timetable.iloc[idx].start_minute\n",
+ " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
+ " # 조정된 현시시간 (prow에 R_n을 곱하고 정수로 바꿈)\n",
+ " adjusted_dur = prow.copy()[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] * R_n\n",
+ " int_parts = adjusted_dur.iloc[0].apply(lambda x: int(x))\n",
+ " frac_parts = adjusted_dur.iloc[0] - int_parts\n",
+ " difference = round(adjusted_dur.iloc[0].sum()) - int_parts.sum()\n",
+ " for _ in range(difference): # 소수 부분이 가장 큰 상위 'difference'개의 값에 대해 올림 처리\n",
+ " max_frac_index = frac_parts.idxmax()\n",
+ " int_parts[max_frac_index] += 1\n",
+ " frac_parts[max_frac_index] = 0 # 이미 처리된 항목은 0으로 설정\n",
+ " # rhist에 조정된 현시시간을 반영\n",
+ " rhist.loc[n, [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] = int_parts.values\n",
+ " rhist.loc[n, 'cycle'] = int_parts.sum().sum() // 2\n",
+ "\n",
+ " if n == rhist.index[-1]:\n",
+ " break\n",
+ " prev_unix = curr_unix\n",
+ " curr_unix = rhist.loc[n+1, 'start_unix']\n",
+ "\n",
+ " # 생략해도 무방할 코드\n",
+ " rhist = rhist.reset_index(drop=True)\n",
+ " rhist = rhist.sort_values(by=['start_unix'])\n",
+ "\n",
+ " # D_n 및 S_n 값 재정의\n",
+ " for n in range(len(rhist)):\n",
+ " curr_unix = rhist.iloc[n].start_unix # current start_unix\n",
+ " rhist.loc[n, ['D_n', 'S_n']] = calculate_DS(rhist, curr_unix)\n",
+ " rhists.append(rhist)\n",
+ " rhists = pd.concat(rhists).sort_values(by=['start_unix','inter_no'])\n",
+ " rhists = rhists[rhists.start_unix >= present_time - 3600]\n",
+ " rhists = rhists.drop(columns=['D_n', 'S_n'])\n",
+ " return rhists"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_hrhists(rhists, isplits, timetable):\n",
+ " # 계층화된 형태로 변환\n",
+ " hrhists = [] # hierarchied recent history\n",
+ " for i, row in rhists.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_unix = row.start_unix\n",
+ "\n",
+ " ind = (timetable['start_seconds'] <= row.start_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[ind].start_hour\n",
+ " start_minute = timetable.iloc[ind].start_minute\n",
+ " isplit = isplits[(inter_no, start_hour, start_minute)]\n",
+ " phas_As = [isplit[j][0] for j in isplit.keys()]\n",
+ " phas_Bs = [isplit[j][1] for j in isplit.keys()]\n",
+ " durs_A = row[[f'dura_A{j}' for j in range(1,9)]]\n",
+ " durs_B = row[[f'dura_B{j}' for j in range(1,9)]]\n",
+ " durations = []\n",
+ " for j in range(1, len(isplit)+1):\n",
+ " ja = isplit[j][0]\n",
+ " jb = isplit[j][1]\n",
+ " if ja == jb:\n",
+ " durations.append(min(durs_A[ja-1], durs_B[jb-1]))\n",
+ " else:\n",
+ " durations.append(abs(durs_A[ja-1] - durs_B[ja-1]))\n",
+ " new_rows = pd.DataFrame({'inter_no':[inter_no] * len(durations), 'start_unix':[start_unix] * len(durations),\n",
+ " 'phas_A':phas_As, 'phas_B':phas_Bs, 'duration':durations})\n",
+ " hrhists.append(new_rows)\n",
+ " hrhists = pd.concat(hrhists)\n",
+ " hrhists = hrhists.sort_values(by = ['start_unix', 'inter_no', 'phas_A', 'phas_B']).reset_index(drop=True)\n",
+ " return hrhists"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_movements():\n",
+ " movements_path = '../../Data/tables/movements/'\n",
+ " movements_list = [pd.read_csv(movements_path + file, index_col=0) for file in tqdm(os.listdir(movements_path))]\n",
+ " movements = pd.concat(movements_list)\n",
+ " movements = movements.drop(columns=['start_unix'])\n",
+ " movements = movements.drop_duplicates()\n",
+ " movements = movements.sort_values(by=['inter_no', 'phas_A', 'phas_B'])\n",
+ " movements = movements.reset_index(drop=True)\n",
+ " movements.to_csv(movements_path + 'movements.csv')\n",
+ " return movements"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def update_movement(hrhists, movement, movements):\n",
+ " # 중복을 제거하고 (inter_no, start_unix) 쌍을 만듭니다.\n",
+ " hrhists_inter_unix = set(hrhists[['inter_no', 'start_unix']].drop_duplicates().itertuples(index=False, name=None))\n",
+ " movement_inter_unix = set(movement[['inter_no', 'start_unix']].drop_duplicates().itertuples(index=False, name=None))\n",
+ "\n",
+ " # hrhists에는 있지만 movement에는 없는 (inter_no, start_unix) 쌍을 찾습니다.\n",
+ " missing_in_movement = hrhists_inter_unix - movement_inter_unix\n",
+ "\n",
+ " # 새로운 행들을 생성합니다.\n",
+ " new_rows = []\n",
+ " for inter_no, start_unix in missing_in_movement:\n",
+ " # movements에서 해당 inter_no의 데이터를 찾습니다.\n",
+ " new_row = movements[movements['inter_no'] == inter_no].copy()\n",
+ " # start_unix 값을 설정합니다.\n",
+ " new_row['start_unix'] = start_unix\n",
+ " new_rows.append(new_row)\n",
+ "\n",
+ " # 새로운 데이터프레임을 생성하고 기존 movement 데이터프레임과 합칩니다.\n",
+ " new_movement = pd.concat(new_rows, ignore_index=True)\n",
+ " movement_updated = pd.concat([movement, new_movement], ignore_index=True)\n",
+ " return movement_updated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_histid(present_time, movedur):\n",
+ " # 이동류 매칭 테이블에서 진입id, 진출id를 가져와서 붙임.\n",
+ " for i, row in movedur.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_unix = row.start_unix\n",
+ " # incoming and outgoing edges A\n",
+ " move_A = row.move_A\n",
+ " if move_A in [17, 18]:\n",
+ " inc_edge_A = np.nan\n",
+ " out_edge_A = np.nan\n",
+ " else:\n",
+ " match_A = matching[(matching.inter_no == inter_no) & (matching.move_no == move_A)].iloc[0]\n",
+ " inc_edge_A = match_A.inc_edge\n",
+ " out_edge_A = match_A.out_edge\n",
+ " movedur.loc[i, ['inc_edge_A', 'out_edge_A']] = [inc_edge_A, out_edge_A]\n",
+ " # incoming and outgoing edges B\n",
+ " move_B = row.move_B\n",
+ " if move_B in [17, 18]:\n",
+ " inc_edge_B = np.nan\n",
+ " out_edge_B = np.nan\n",
+ " else:\n",
+ " match_B = matching[(matching.inter_no == inter_no) & (matching.move_no == move_B)].iloc[0]\n",
+ " inc_edge_B = match_B.inc_edge\n",
+ " out_edge_B = match_B.out_edge\n",
+ " movedur.loc[i, ['inc_edge_B', 'out_edge_B']] = [inc_edge_B, out_edge_B]\n",
+ "\n",
+ " # 이동류 컬럼 제거\n",
+ " movedur = movedur.drop(['move_A', 'move_B'], axis=1)\n",
+ "\n",
+ " histid = movedur.copy() # history with edge ids (incoming and outgoing edge ids)\n",
+ " histid['node_id'] = histid['inter_no'].map(inter2node)\n",
+ " histid = histid[['inter_no', 'node_id', 'start_unix', 'phas_A', 'phas_B', 'duration', 'inc_edge_A', 'out_edge_A', 'inc_edge_B', 'out_edge_B']]\n",
+ " histid = histid[histid.start_unix > present_time - 3600]\n",
+ " return histid"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 44,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def histid_main(m):\n",
+ " '''\n",
+ " 통합테이블(histid)를 만드는 함수\n",
+ "\n",
+ " input : m\n",
+ " - m ranges from 0 to 287, but 0 makes an error where 288 = 86400//300\n",
+ " - present_time = fmins[m] : 현재시점\n",
+ "\n",
+ " output : histid (통합테이블, HISTory with edge_IDs)\n",
+ " - 컬럼 : inter_no, node_id, start_unix, phas_A, phas_B, duration, inc_edge_A, out_edge_A, inc_edge_B, out_edge_B\n",
+ "\n",
+ " 주요 데이터, 중간산출물 및 결과물 :\n",
+ " # 데이터\n",
+ " - history : 신호이력 (inter_no, end_unix, dura_Aj, dura_Bj, cycle, offset)\n",
+ " - plan : 신호계획 (inter_no, start_hour, start_minute, dura_Aj, dura_Bj cycle, offset)\n",
+ " # 중간산출물\n",
+ " - rhists (recent history)\n",
+ " - history에서 현재 시각 이전의 데이터를 가져옴.\n",
+ " - end_unix를 start_unix로 변환\n",
+ " - 참값판단 프로세스(결측·이상치 처리)\n",
+ " - 컬럼 : inter_no, start_unix, dura_Aj, dura_Bj, cycle\n",
+ " - hrhists (hierarchized recent history)\n",
+ " - rhists를 계층화\n",
+ " - 컬럼 : inter_no, start_unix, phas_A, phas_B, duration\n",
+ " - movements\n",
+ " - 각 교차로에 대하여 현시별로 이동류를 정해놓음.\n",
+ " - join시 사용하기 위함.\n",
+ " - 한 번 만들어놓고 두고두고 사용함.\n",
+ " - 컬럼 : inter_no, phas_A, phas_B, move_A, move_B\n",
+ " - movement\n",
+ " - 현재 시점에서의 이동류정보\n",
+ " - 컬럼 : inter_no, phas_A, phas_B, move_A, move_B, start_unix\n",
+ " - movement_updated\n",
+ " - movement와 hrhists를 join하기 전에, movement에는 없지만 hrhists에는 있는 start_unix에 대한 이동류 정보를 가져와 movement에 붙임\n",
+ " - 이동류정보는 앞서 정의한 movements에서 가져옴.\n",
+ " - 컬럼 : inter_no, phas_A, phas_B, move_A, move_B, start_unix\n",
+ " - movedur\n",
+ " - hrhists와 movement_updated를 join\n",
+ " - 컬럼 : inter_no, phas_A, phas_B, move_A, move_B, start_unix, duration\n",
+ " # 결과\n",
+ "\n",
+ " '''\n",
+ " midnight = int(datetime(2024, 1, 5, 0, 0, 0).timestamp())\n",
+ " next_day = int(datetime(2024, 1, 6, 0, 0, 0).timestamp())\n",
+ " fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
+ "\n",
+ " # 사용할 표준 테이블 목록\n",
+ " plan = pd.read_csv('../../Data/tables/plan.csv', index_col=0)\n",
+ " history = pd.read_csv('../../Data/tables/history.csv', index_col=0)\n",
+ "\n",
+ " # 참고할 딕셔너리, 데이터프레임 등 목록\n",
+ " splits, isplits = make_splits(plan)\n",
+ " timetable = make_timetable(plan)\n",
+ "\n",
+ " # 현재시점\n",
+ " present_time = fmins[m]\n",
+ " print(datetime.fromtimestamp(present_time))\n",
+ "\n",
+ " # rhists, hrhists\n",
+ " rhists = make_rhists(present_time, timetable, plan, history)\n",
+ " hrhists = make_hrhists(rhists, isplits, timetable)\n",
+ "\n",
+ " # movements, movement, movement_updated\n",
+ " movements = pd.read_csv('../../data/tables/movements/movements.csv', index_col=0)\n",
+ " movement = pd.read_csv(f'../../Data/tables/movements/movements_{present_time}.csv', index_col=0)\n",
+ " movement_updated = update_movement(hrhists, movement, movements)\n",
+ "\n",
+ " # movedur\n",
+ " movedur = pd.merge(movement_updated, hrhists, how='inner', on=['inter_no', 'start_unix', 'phas_A', 'phas_B']) # movements and durations\n",
+ " movedur = movedur.sort_values(by=['start_unix', 'inter_no', 'phas_A','phas_B'])\n",
+ " movedur = movedur[['inter_no', 'start_unix', 'phas_A', 'phas_B', 'move_A', 'move_B', 'duration']]\n",
+ "\n",
+ " # histid\n",
+ " histid = make_histid(present_time, movedur)\n",
+ "\n",
+ " \n",
+ " # hrhists['start_dt'] = hrhists['start_unix'].map(lambda x:datetime.fromtimestamp(x))\n",
+ "\n",
+ " return histid"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 45,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2024-01-05 02:30:00\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " node_id | \n",
+ " start_unix | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " duration | \n",
+ " inc_edge_A | \n",
+ " out_edge_A | \n",
+ " inc_edge_B | \n",
+ " out_edge_B | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " u00 | \n",
+ " 1704385840 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " u00 | \n",
+ " 1704385840 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " u00 | \n",
+ " 1704385840 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 25 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " u00 | \n",
+ " 1704385840 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 30 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " u00 | \n",
+ " 1704385840 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 764 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704389220 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 17 | \n",
+ " 571500617_02 | \n",
+ " 571500618_01 | \n",
+ " 571500618_02 | \n",
+ " 571500617_01 | \n",
+ "
\n",
+ " \n",
+ " 765 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704389220 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 58 | \n",
+ " 571500617_02 | \n",
+ " 571500618_01 | \n",
+ " 571500617_02 | \n",
+ " 571500569_01 | \n",
+ "
\n",
+ " \n",
+ " 766 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704389220 | \n",
+ " 5 | \n",
+ " 5 | \n",
+ " 17 | \n",
+ " 571500583_01 | \n",
+ " 571500617_01 | \n",
+ " 571500583_01 | \n",
+ " 571500569_01 | \n",
+ "
\n",
+ " \n",
+ " 767 | \n",
+ " 202 | \n",
+ " i9 | \n",
+ " 1704389220 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 39 | \n",
+ " 571510152_02 | \n",
+ " -571510152_01 | \n",
+ " 571510152_01 | \n",
+ " 571510152_01.65 | \n",
+ "
\n",
+ " \n",
+ " 768 | \n",
+ " 202 | \n",
+ " i9 | \n",
+ " 1704389220 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 101 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
769 rows × 10 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no node_id start_unix phas_A phas_B duration inc_edge_A \\\n",
+ "0 175 u00 1704385840 1 1 37 -571542797_02 \n",
+ "1 175 u00 1704385840 2 2 39 -571500487_01 \n",
+ "2 175 u00 1704385840 3 3 25 571545870_02 \n",
+ "3 175 u00 1704385840 3 4 30 571545870_02 \n",
+ "4 175 u00 1704385840 4 4 29 571510153_02 \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "764 201 i8 1704389220 3 3 17 571500617_02 \n",
+ "765 201 i8 1704389220 4 4 58 571500617_02 \n",
+ "766 201 i8 1704389220 5 5 17 571500583_01 \n",
+ "767 202 i9 1704389220 1 1 39 571510152_02 \n",
+ "768 202 i9 1704389220 2 2 101 NaN \n",
+ "\n",
+ " out_edge_A inc_edge_B out_edge_B \n",
+ "0 571500487_01 -571500487_01 571542797_02 \n",
+ "1 571545870_01 -571542797_02 571510153_01 \n",
+ "2 571510153_01 571545870_02 571542797_02 \n",
+ "3 571510153_01 571510153_02 571545870_01 \n",
+ "4 571500487_01 571510153_02 571545870_01 \n",
+ ".. ... ... ... \n",
+ "764 571500618_01 571500618_02 571500617_01 \n",
+ "765 571500618_01 571500617_02 571500569_01 \n",
+ "766 571500617_01 571500583_01 571500569_01 \n",
+ "767 -571510152_01 571510152_01 571510152_01.65 \n",
+ "768 NaN NaN NaN \n",
+ "\n",
+ "[769 rows x 10 columns]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2024-01-05 02:35:00\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " node_id | \n",
+ " start_unix | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " duration | \n",
+ " inc_edge_A | \n",
+ " out_edge_A | \n",
+ " inc_edge_B | \n",
+ " out_edge_B | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704386139 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 24 | \n",
+ " -571500569_01 | \n",
+ " 571500583_02 | \n",
+ " -571500569_01 | \n",
+ " 571500618_01 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704386139 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 24 | \n",
+ " 571500618_02 | \n",
+ " 571500583_02 | \n",
+ " 571500618_02 | \n",
+ " 571500617_01 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704386139 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 17 | \n",
+ " 571500617_02 | \n",
+ " 571500618_01 | \n",
+ " 571500618_02 | \n",
+ " 571500617_01 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704386139 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 58 | \n",
+ " 571500617_02 | \n",
+ " 571500618_01 | \n",
+ " 571500617_02 | \n",
+ " 571500569_01 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704386139 | \n",
+ " 5 | \n",
+ " 5 | \n",
+ " 17 | \n",
+ " 571500583_01 | \n",
+ " 571500617_01 | \n",
+ " 571500583_01 | \n",
+ " 571500569_01 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 768 | \n",
+ " 175 | \n",
+ " u00 | \n",
+ " 1704389520 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 769 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704389520 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 33 | \n",
+ " -571511538_02 | \n",
+ " 571542073_02 | \n",
+ " 571542073_01 | \n",
+ " 571511538_02 | \n",
+ "
\n",
+ " \n",
+ " 770 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704389520 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 35 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ " 771 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704389520 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 26 | \n",
+ " -571511538_02 | \n",
+ " 571542073_02 | \n",
+ " 571542073_01 | \n",
+ " 571511538_02 | \n",
+ "
\n",
+ " \n",
+ " 772 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704389520 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 26 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
773 rows × 10 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no node_id start_unix phas_A phas_B duration inc_edge_A \\\n",
+ "0 201 i8 1704386139 1 1 24 -571500569_01 \n",
+ "1 201 i8 1704386139 2 2 24 571500618_02 \n",
+ "2 201 i8 1704386139 3 3 17 571500617_02 \n",
+ "3 201 i8 1704386139 4 4 58 571500617_02 \n",
+ "4 201 i8 1704386139 5 5 17 571500583_01 \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "768 175 u00 1704389520 4 4 29 571510153_02 \n",
+ "769 206 i7 1704389520 1 1 33 -571511538_02 \n",
+ "770 206 i7 1704389520 2 2 35 NaN \n",
+ "771 206 i7 1704389520 3 3 26 -571511538_02 \n",
+ "772 206 i7 1704389520 4 4 26 NaN \n",
+ "\n",
+ " out_edge_A inc_edge_B out_edge_B \n",
+ "0 571500583_02 -571500569_01 571500618_01 \n",
+ "1 571500583_02 571500618_02 571500617_01 \n",
+ "2 571500618_01 571500618_02 571500617_01 \n",
+ "3 571500618_01 571500617_02 571500569_01 \n",
+ "4 571500617_01 571500583_01 571500569_01 \n",
+ ".. ... ... ... \n",
+ "768 571500487_01 571510153_02 571545870_01 \n",
+ "769 571542073_02 571542073_01 571511538_02 \n",
+ "770 NaN NaN NaN \n",
+ "771 571542073_02 571542073_01 571511538_02 \n",
+ "772 NaN NaN NaN \n",
+ "\n",
+ "[773 rows x 10 columns]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "for m in range(30, 32):\n",
+ " histid = histid_main(m)\n",
+ " display(histid)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "rts",
+ "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.8.10"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/Analysis/0109_preprocess/0122_preprocess_9.ipynb b/Analysis/0109_preprocess/0122_preprocess_9.ipynb
index f965c317a..b2236f2f2 100644
--- a/Analysis/0109_preprocess/0122_preprocess_9.ipynb
+++ b/Analysis/0109_preprocess/0122_preprocess_9.ipynb
@@ -26,7982 +26,755 @@
"cell_type": "code",
"execution_count": 2,
"metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- " 0%| | 0/17280 [00:00, ?it/s]"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "100%|██████████| 17280/17280 [00:13<00:00, 1294.28it/s]\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phas_A | \n",
- " phas_B | \n",
- " move_A | \n",
- " move_B | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 175 | \n",
- " 1 | \n",
- " 1 | \n",
- " 8 | \n",
- " 4 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 175 | \n",
- " 2 | \n",
- " 2 | \n",
- " 7 | \n",
- " 3 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 175 | \n",
- " 3 | \n",
- " 3 | \n",
- " 6 | \n",
- " 1 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 175 | \n",
- " 3 | \n",
- " 4 | \n",
- " 6 | \n",
- " 2 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 175 | \n",
- " 4 | \n",
- " 4 | \n",
- " 5 | \n",
- " 2 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 176 | \n",
- " 1 | \n",
- " 1 | \n",
- " 8 | \n",
- " 4 | \n",
- "
\n",
- " \n",
- " 6 | \n",
- " 176 | \n",
- " 2 | \n",
- " 2 | \n",
- " 8 | \n",
- " 3 | \n",
- "
\n",
- " \n",
- " 7 | \n",
- " 176 | \n",
- " 3 | \n",
- " 3 | \n",
- " 5 | \n",
- " 18 | \n",
- "
\n",
- " \n",
- " 8 | \n",
- " 177 | \n",
- " 1 | \n",
- " 1 | \n",
- " 8 | \n",
- " 4 | \n",
- "
\n",
- " \n",
- " 9 | \n",
- " 177 | \n",
- " 2 | \n",
- " 2 | \n",
- " 7 | \n",
- " 3 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phas_A phas_B move_A move_B\n",
- "0 175 1 1 8 4\n",
- "1 175 2 2 7 3\n",
- "2 175 3 3 6 1\n",
- "3 175 3 4 6 2\n",
- "4 175 4 4 5 2\n",
- "5 176 1 1 8 4\n",
- "6 176 2 2 8 3\n",
- "7 176 3 3 5 18\n",
- "8 177 1 1 8 4\n",
- "9 177 2 2 7 3"
- ]
- },
- "execution_count": 2,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# [이동류번호] 불러오기 (약 1분의 소요시간)\n",
- "path_moves = '../../Data/tables/moves/'\n",
- "csv_moves = os.listdir('../../Data/tables/moves/')\n",
- "moves = [pd.read_csv(path_moves + csv_move, index_col=0) for csv_move in tqdm(csv_moves)]\n",
- "match1 = pd.concat(moves).drop_duplicates().sort_values(by=['inter_no','phas_A','phas_B']).reset_index(drop=True)\n",
- "match1.head(10)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phase_no | \n",
- " ring_type | \n",
- " move_no | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 175 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- "
\n",
- " \n",
- " 0 | \n",
- " 175 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 175 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 175 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 175 | \n",
- " 3 | \n",
- " A | \n",
- " 6 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 175 | \n",
- " 3 | \n",
- " B | \n",
- " 1 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 175 | \n",
- " 4 | \n",
- " A | \n",
- " 5 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 175 | \n",
- " 4 | \n",
- " B | \n",
- " 2 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 176 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 176 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phase_no ring_type move_no\n",
- "0 175 1 A 8\n",
- "0 175 1 B 4\n",
- "1 175 2 A 7\n",
- "1 175 2 B 3\n",
- "2 175 3 A 6\n",
- "2 175 3 B 1\n",
- "4 175 4 A 5\n",
- "3 175 4 B 2\n",
- "5 176 1 A 8\n",
- "5 176 1 B 4"
- ]
- },
- "execution_count": 3,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 계층화 (inter_no, phas_A, phas_B, move_A, move_B) -> ('inter_no', 'phase_no', 'ring_type', 'move_no')\n",
- "matchA = match1[['inter_no', 'phas_A', 'move_A']].copy()\n",
- "matchA.columns = ['inter_no', 'phase_no', 'move_no']\n",
- "matchA['ring_type'] = 'A'\n",
- "matchB = match1[['inter_no', 'phas_B', 'move_B']].copy()\n",
- "matchB.columns = ['inter_no', 'phase_no', 'move_no']\n",
- "matchB['ring_type'] = 'B'\n",
- "match2 = pd.concat([matchA, matchB]).drop_duplicates()\n",
- "match2 = match2[['inter_no', 'phase_no', 'ring_type', 'move_no']]\n",
- "match2 = match2.sort_values(by=list(match2.columns))\n",
- "match2.head(10)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phase_no | \n",
- " ring_type | \n",
- " move_no | \n",
- " inc_dir | \n",
- " out_dir | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 175 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 175 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 175 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 175 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 175 | \n",
- " 3 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 175 | \n",
- " 3 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- "
\n",
- " \n",
- " 6 | \n",
- " 175 | \n",
- " 4 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 7 | \n",
- " 175 | \n",
- " 4 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- "
\n",
- " \n",
- " 8 | \n",
- " 176 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 9 | \n",
- " 176 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- "
\n",
- " \n",
- " 10 | \n",
- " 176 | \n",
- " 2 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 11 | \n",
- " 176 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- "
\n",
- " \n",
- " 12 | \n",
- " 176 | \n",
- " 3 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 13 | \n",
- " 176 | \n",
- " 3 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 14 | \n",
- " 177 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 15 | \n",
- " 177 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- "
\n",
- " \n",
- " 16 | \n",
- " 177 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- "
\n",
- " \n",
- " 17 | \n",
- " 177 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- "
\n",
- " \n",
- " 18 | \n",
- " 177 | \n",
- " 3 | \n",
- " A | \n",
- " 17 | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 19 | \n",
- " 177 | \n",
- " 3 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 20 | \n",
- " 177 | \n",
- " 4 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 21 | \n",
- " 177 | \n",
- " 4 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- "
\n",
- " \n",
- " 22 | \n",
- " 178 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 23 | \n",
- " 178 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- "
\n",
- " \n",
- " 24 | \n",
- " 178 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- "
\n",
- " \n",
- " 25 | \n",
- " 178 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- "
\n",
- " \n",
- " 26 | \n",
- " 178 | \n",
- " 3 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 27 | \n",
- " 178 | \n",
- " 3 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- "
\n",
- " \n",
- " 28 | \n",
- " 178 | \n",
- " 4 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- "
\n",
- " \n",
- " 29 | \n",
- " 178 | \n",
- " 4 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- "
\n",
- " \n",
- " 30 | \n",
- " 201 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 31 | \n",
- " 201 | \n",
- " 1 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- "
\n",
- " \n",
- " 32 | \n",
- " 201 | \n",
- " 2 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 33 | \n",
- " 201 | \n",
- " 2 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- "
\n",
- " \n",
- " 34 | \n",
- " 201 | \n",
- " 3 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- "
\n",
- " \n",
- " 35 | \n",
- " 201 | \n",
- " 3 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- "
\n",
- " \n",
- " 36 | \n",
- " 201 | \n",
- " 4 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- "
\n",
- " \n",
- " 37 | \n",
- " 201 | \n",
- " 4 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- "
\n",
- " \n",
- " 38 | \n",
- " 201 | \n",
- " 5 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- "
\n",
- " \n",
- " 39 | \n",
- " 201 | \n",
- " 5 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- "
\n",
- " \n",
- " 40 | \n",
- " 202 | \n",
- " 1 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- "
\n",
- " \n",
- " 41 | \n",
- " 202 | \n",
- " 1 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- "
\n",
- " \n",
- " 42 | \n",
- " 202 | \n",
- " 2 | \n",
- " A | \n",
- " 17 | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 43 | \n",
- " 202 | \n",
- " 2 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 44 | \n",
- " 206 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 45 | \n",
- " 206 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- "
\n",
- " \n",
- " 46 | \n",
- " 206 | \n",
- " 2 | \n",
- " A | \n",
- " 17 | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 47 | \n",
- " 206 | \n",
- " 2 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 48 | \n",
- " 206 | \n",
- " 3 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 49 | \n",
- " 206 | \n",
- " 3 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- "
\n",
- " \n",
- " 50 | \n",
- " 206 | \n",
- " 4 | \n",
- " A | \n",
- " 17 | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 51 | \n",
- " 206 | \n",
- " 4 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 52 | \n",
- " 210 | \n",
- " 1 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- "
\n",
- " \n",
- " 53 | \n",
- " 210 | \n",
- " 1 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 54 | \n",
- " 210 | \n",
- " 2 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 55 | \n",
- " 210 | \n",
- " 2 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- "
\n",
- " \n",
- " 56 | \n",
- " 210 | \n",
- " 3 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- "
\n",
- " \n",
- " 57 | \n",
- " 210 | \n",
- " 3 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- "
\n",
- " \n",
- " 58 | \n",
- " 210 | \n",
- " 4 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- "
\n",
- " \n",
- " 59 | \n",
- " 210 | \n",
- " 4 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phase_no ring_type move_no inc_dir out_dir\n",
- "0 175 1 A 8 남 북\n",
- "1 175 1 B 4 북 남\n",
- "2 175 2 A 7 북 동\n",
- "3 175 2 B 3 남 서\n",
- "4 175 3 A 6 동 서\n",
- "5 175 3 B 1 동 남\n",
- "6 175 4 A 5 서 북\n",
- "7 175 4 B 2 서 동\n",
- "8 176 1 A 8 남 북\n",
- "9 176 1 B 4 북 남\n",
- "10 176 2 A 8 남 북\n",
- "11 176 2 B 3 남 서\n",
- "12 176 3 A 5 서 북\n",
- "13 176 3 B 18 NaN NaN\n",
- "14 177 1 A 8 남 북\n",
- "15 177 1 B 4 북 남\n",
- "16 177 2 A 7 북 동\n",
- "17 177 2 B 3 남 서\n",
- "18 177 3 A 17 NaN NaN\n",
- "19 177 3 B 18 NaN NaN\n",
- "20 177 4 A 5 서 북\n",
- "21 177 4 B 1 동 남\n",
- "22 178 1 A 8 남 북\n",
- "23 178 1 B 4 북 남\n",
- "24 178 2 A 7 북 동\n",
- "25 178 2 B 3 남 서\n",
- "26 178 3 A 5 서 북\n",
- "27 178 3 B 2 서 동\n",
- "28 178 4 A 6 동 서\n",
- "29 178 4 B 1 동 남\n",
- "30 201 1 A 8 남 북\n",
- "31 201 1 B 3 남 서\n",
- "32 201 2 A 5 서 북\n",
- "33 201 2 B 2 서 동\n",
- "34 201 3 A 6 동 서\n",
- "35 201 3 B 2 서 동\n",
- "36 201 4 A 6 동 서\n",
- "37 201 4 B 1 동 남\n",
- "38 201 5 A 7 북 동\n",
- "39 201 5 B 4 북 남\n",
- "40 202 1 A 6 동 서\n",
- "41 202 1 B 2 서 동\n",
- "42 202 2 A 17 NaN NaN\n",
- "43 202 2 B 18 NaN NaN\n",
- "44 206 1 A 8 남 북\n",
- "45 206 1 B 4 북 남\n",
- "46 206 2 A 17 NaN NaN\n",
- "47 206 2 B 18 NaN NaN\n",
- "48 206 3 A 8 남 북\n",
- "49 206 3 B 4 북 남\n",
- "50 206 4 A 17 NaN NaN\n",
- "51 206 4 B 18 NaN NaN\n",
- "52 210 1 A 6 동 서\n",
- "53 210 1 B 18 NaN NaN\n",
- "54 210 2 A 5 서 북\n",
- "55 210 2 B 2 서 동\n",
- "56 210 3 A 7 북 동\n",
- "57 210 3 B 4 북 남\n",
- "58 210 4 A 8 남 북\n",
- "59 210 4 B 3 남 서"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# [nema 이동류목록] 불러오기 및 병합\n",
- "nema = pd.read_csv('../../Data/tables/nema.csv', encoding='cp949')\n",
- "match3 = pd.merge(match2, nema, how='left', on='move_no').drop_duplicates()\n",
- "match3"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phase_no | \n",
- " ring_type | \n",
- " move_no | \n",
- " inc_dir | \n",
- " out_dir | \n",
- " inc_angle | \n",
- " out_angle | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 175 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 179 | \n",
- " 004 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 175 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 003 | \n",
- " 176 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 175 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 001 | \n",
- " 095 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 175 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 179 | \n",
- " 270 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 175 | \n",
- " 3 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 175 | \n",
- " 3 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- " 090 | \n",
- " 180 | \n",
- "
\n",
- " \n",
- " 6 | \n",
- " 175 | \n",
- " 4 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 268 | \n",
- " 000 | \n",
- "
\n",
- " \n",
- " 7 | \n",
- " 175 | \n",
- " 4 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- "
\n",
- " \n",
- " 8 | \n",
- " 176 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- "
\n",
- " \n",
- " 9 | \n",
- " 176 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 359 | \n",
- " 180 | \n",
- "
\n",
- " \n",
- " 10 | \n",
- " 176 | \n",
- " 2 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- "
\n",
- " \n",
- " 11 | \n",
- " 176 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 180 | \n",
- " 270 | \n",
- "
\n",
- " \n",
- " 12 | \n",
- " 176 | \n",
- " 3 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 270 | \n",
- " 356 | \n",
- "
\n",
- " \n",
- " 13 | \n",
- " 176 | \n",
- " 3 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 14 | \n",
- " 177 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- "
\n",
- " \n",
- " 15 | \n",
- " 177 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 001 | \n",
- " 176 | \n",
- "
\n",
- " \n",
- " 16 | \n",
- " 177 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 000 | \n",
- " 090 | \n",
- "
\n",
- " \n",
- " 17 | \n",
- " 177 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 179 | \n",
- " 270 | \n",
- "
\n",
- " \n",
- " 18 | \n",
- " 177 | \n",
- " 3 | \n",
- " A | \n",
- " 17 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 19 | \n",
- " 177 | \n",
- " 3 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 20 | \n",
- " 177 | \n",
- " 4 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 268 | \n",
- " 000 | \n",
- "
\n",
- " \n",
- " 21 | \n",
- " 177 | \n",
- " 4 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- " 090 | \n",
- " 180 | \n",
- "
\n",
- " \n",
- " 22 | \n",
- " 178 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- "
\n",
- " \n",
- " 23 | \n",
- " 178 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- "
\n",
- " \n",
- " 24 | \n",
- " 178 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 000 | \n",
- " 090 | \n",
- "
\n",
- " \n",
- " 25 | \n",
- " 178 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 180 | \n",
- " 270 | \n",
- "
\n",
- " \n",
- " 26 | \n",
- " 178 | \n",
- " 3 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 270 | \n",
- " 000 | \n",
- "
\n",
- " \n",
- " 27 | \n",
- " 178 | \n",
- " 3 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- "
\n",
- " \n",
- " 28 | \n",
- " 178 | \n",
- " 4 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- "
\n",
- " \n",
- " 29 | \n",
- " 178 | \n",
- " 4 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- " 090 | \n",
- " 180 | \n",
- "
\n",
- " \n",
- " 30 | \n",
- " 201 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- "
\n",
- " \n",
- " 31 | \n",
- " 201 | \n",
- " 1 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 180 | \n",
- " 270 | \n",
- "
\n",
- " \n",
- " 32 | \n",
- " 201 | \n",
- " 2 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 270 | \n",
- " 000 | \n",
- "
\n",
- " \n",
- " 33 | \n",
- " 201 | \n",
- " 2 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- "
\n",
- " \n",
- " 34 | \n",
- " 201 | \n",
- " 3 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- "
\n",
- " \n",
- " 35 | \n",
- " 201 | \n",
- " 3 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- "
\n",
- " \n",
- " 36 | \n",
- " 201 | \n",
- " 4 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- "
\n",
- " \n",
- " 37 | \n",
- " 201 | \n",
- " 4 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- " 090 | \n",
- " 180 | \n",
- "
\n",
- " \n",
- " 38 | \n",
- " 201 | \n",
- " 5 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 000 | \n",
- " 090 | \n",
- "
\n",
- " \n",
- " 39 | \n",
- " 201 | \n",
- " 5 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- "
\n",
- " \n",
- " 40 | \n",
- " 202 | \n",
- " 1 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- "
\n",
- " \n",
- " 41 | \n",
- " 202 | \n",
- " 1 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- "
\n",
- " \n",
- " 42 | \n",
- " 202 | \n",
- " 2 | \n",
- " A | \n",
- " 17 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 43 | \n",
- " 202 | \n",
- " 2 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 44 | \n",
- " 206 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- "
\n",
- " \n",
- " 45 | \n",
- " 206 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- "
\n",
- " \n",
- " 46 | \n",
- " 206 | \n",
- " 2 | \n",
- " A | \n",
- " 17 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 47 | \n",
- " 206 | \n",
- " 2 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 48 | \n",
- " 206 | \n",
- " 3 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- "
\n",
- " \n",
- " 49 | \n",
- " 206 | \n",
- " 3 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- "
\n",
- " \n",
- " 50 | \n",
- " 206 | \n",
- " 4 | \n",
- " A | \n",
- " 17 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 51 | \n",
- " 206 | \n",
- " 4 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 52 | \n",
- " 210 | \n",
- " 1 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- "
\n",
- " \n",
- " 53 | \n",
- " 210 | \n",
- " 1 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 54 | \n",
- " 210 | \n",
- " 2 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 268 | \n",
- " 000 | \n",
- "
\n",
- " \n",
- " 55 | \n",
- " 210 | \n",
- " 2 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- "
\n",
- " \n",
- " 56 | \n",
- " 210 | \n",
- " 3 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 359 | \n",
- " 090 | \n",
- "
\n",
- " \n",
- " 57 | \n",
- " 210 | \n",
- " 3 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- "
\n",
- " \n",
- " 58 | \n",
- " 210 | \n",
- " 4 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- "
\n",
- " \n",
- " 59 | \n",
- " 210 | \n",
- " 4 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 180 | \n",
- " 270 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle\n",
- "0 175 1 A 8 남 북 179 004\n",
- "1 175 1 B 4 북 남 003 176\n",
- "2 175 2 A 7 북 동 001 095\n",
- "3 175 2 B 3 남 서 179 270\n",
- "4 175 3 A 6 동 서 090 270\n",
- "5 175 3 B 1 동 남 090 180\n",
- "6 175 4 A 5 서 북 268 000\n",
- "7 175 4 B 2 서 동 270 090\n",
- "8 176 1 A 8 남 북 180 000\n",
- "9 176 1 B 4 북 남 359 180\n",
- "10 176 2 A 8 남 북 180 000\n",
- "11 176 2 B 3 남 서 180 270\n",
- "12 176 3 A 5 서 북 270 356\n",
- "13 176 3 B 18 NaN NaN NaN NaN\n",
- "14 177 1 A 8 남 북 180 000\n",
- "15 177 1 B 4 북 남 001 176\n",
- "16 177 2 A 7 북 동 000 090\n",
- "17 177 2 B 3 남 서 179 270\n",
- "18 177 3 A 17 NaN NaN NaN NaN\n",
- "19 177 3 B 18 NaN NaN NaN NaN\n",
- "20 177 4 A 5 서 북 268 000\n",
- "21 177 4 B 1 동 남 090 180\n",
- "22 178 1 A 8 남 북 180 000\n",
- "23 178 1 B 4 북 남 000 180\n",
- "24 178 2 A 7 북 동 000 090\n",
- "25 178 2 B 3 남 서 180 270\n",
- "26 178 3 A 5 서 북 270 000\n",
- "27 178 3 B 2 서 동 270 090\n",
- "28 178 4 A 6 동 서 090 270\n",
- "29 178 4 B 1 동 남 090 180\n",
- "30 201 1 A 8 남 북 180 000\n",
- "31 201 1 B 3 남 서 180 270\n",
- "32 201 2 A 5 서 북 270 000\n",
- "33 201 2 B 2 서 동 270 090\n",
- "34 201 3 A 6 동 서 090 270\n",
- "35 201 3 B 2 서 동 270 090\n",
- "36 201 4 A 6 동 서 090 270\n",
- "37 201 4 B 1 동 남 090 180\n",
- "38 201 5 A 7 북 동 000 090\n",
- "39 201 5 B 4 북 남 000 180\n",
- "40 202 1 A 6 동 서 090 270\n",
- "41 202 1 B 2 서 동 270 090\n",
- "42 202 2 A 17 NaN NaN NaN NaN\n",
- "43 202 2 B 18 NaN NaN NaN NaN\n",
- "44 206 1 A 8 남 북 180 000\n",
- "45 206 1 B 4 북 남 000 180\n",
- "46 206 2 A 17 NaN NaN NaN NaN\n",
- "47 206 2 B 18 NaN NaN NaN NaN\n",
- "48 206 3 A 8 남 북 180 000\n",
- "49 206 3 B 4 북 남 000 180\n",
- "50 206 4 A 17 NaN NaN NaN NaN\n",
- "51 206 4 B 18 NaN NaN NaN NaN\n",
- "52 210 1 A 6 동 서 090 270\n",
- "53 210 1 B 18 NaN NaN NaN NaN\n",
- "54 210 2 A 5 서 북 268 000\n",
- "55 210 2 B 2 서 동 270 090\n",
- "56 210 3 A 7 북 동 359 090\n",
- "57 210 3 B 4 북 남 000 180\n",
- "58 210 4 A 8 남 북 180 000\n",
- "59 210 4 B 3 남 서 180 270"
- ]
- },
- "execution_count": 5,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# [방위각정보] 불러오기, 계층화, 병합\n",
- "# 불러오기\n",
- "dtype_dict = {f'angle_{alph}{j}':'str' for alph in ['A', 'B'] for j in range(1,9)}\n",
- "angle_original = pd.read_csv('../../Data/tables/angle.csv', index_col=0, dtype = dtype_dict)\n",
- "# 계층화\n",
- "angle = []\n",
- "for i, row in angle_original.iterrows():\n",
- " angle_codes = row[[f'angle_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
- " new = pd.DataFrame({'inter_no':[row.inter_no] * 16, 'phase_no':list(range(1, 9))*2, 'ring_type':['A'] * 8 + ['B'] * 8, 'angle_code':angle_codes.to_list()})\n",
- " angle.append(new)\n",
- "angle = pd.concat(angle)\n",
- "angle = angle.dropna().reset_index(drop=True)\n",
- "# 병합\n",
- "six_chars = angle.angle_code.apply(lambda x:len(x)==6)\n",
- "angle.loc[six_chars,'inc_angle'] = angle.angle_code.apply(lambda x:x[:3])\n",
- "angle.loc[six_chars,'out_angle'] = angle.angle_code.apply(lambda x:x[3:])\n",
- "angle = angle.drop('angle_code', axis=1)\n",
- "match4 = pd.merge(match3, angle, how='left', left_on=['inter_no', 'phase_no', 'ring_type'],\n",
- " right_on=['inter_no', 'phase_no', 'ring_type']).drop_duplicates()\n",
- "match4"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phase_no | \n",
- " ring_type | \n",
- " move_no | \n",
- " inc_dir | \n",
- " out_dir | \n",
- " inc_angle | \n",
- " out_angle | \n",
- " inc_edge | \n",
- " out_edge | \n",
- " node_id | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 175 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 179 | \n",
- " 004 | \n",
- " -571542797_02 | \n",
- " 571500487_01 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 175 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 003 | \n",
- " 176 | \n",
- " -571500487_01 | \n",
- " 571542797_02 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 175 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 001 | \n",
- " 095 | \n",
- " -571500487_01 | \n",
- " 571545870_01 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 175 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 179 | \n",
- " 270 | \n",
- " -571542797_02 | \n",
- " 571510153_01 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 175 | \n",
- " 3 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- " 571545870_02 | \n",
- " 571510153_01 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 175 | \n",
- " 3 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- " 090 | \n",
- " 180 | \n",
- " 571545870_02 | \n",
- " 571542797_02 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 6 | \n",
- " 175 | \n",
- " 4 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 268 | \n",
- " 000 | \n",
- " 571510153_02 | \n",
- " 571500487_01 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 7 | \n",
- " 175 | \n",
- " 4 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- " 571510153_02 | \n",
- " 571545870_01 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 8 | \n",
- " 176 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- " -571542810_01 | \n",
- " -571542797_02.99 | \n",
- " i1 | \n",
- "
\n",
- " \n",
- " 9 | \n",
- " 176 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 359 | \n",
- " 180 | \n",
- " 571542797_02.99 | \n",
- " 571542810_01 | \n",
- " i1 | \n",
- "
\n",
- " \n",
- " 10 | \n",
- " 176 | \n",
- " 2 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- " -571542810_01 | \n",
- " -571542797_02.99 | \n",
- " i1 | \n",
- "
\n",
- " \n",
- " 11 | \n",
- " 176 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 180 | \n",
- " 270 | \n",
- " -571542810_01 | \n",
- " 571543469_01 | \n",
- " i1 | \n",
- "
\n",
- " \n",
- " 12 | \n",
- " 176 | \n",
- " 3 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 270 | \n",
- " 356 | \n",
- " 571543469_02 | \n",
- " -571542797_02.99 | \n",
- " i1 | \n",
- "
\n",
- " \n",
- " 13 | \n",
- " 176 | \n",
- " 3 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " i1 | \n",
- "
\n",
- " \n",
- " 14 | \n",
- " 177 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- " -571542809_01 | \n",
- " 571542811_01 | \n",
- " i2 | \n",
- "
\n",
- " \n",
- " 15 | \n",
- " 177 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 001 | \n",
- " 176 | \n",
- " 571542811_02 | \n",
- " 571542809_01 | \n",
- " i2 | \n",
- "
\n",
- " \n",
- " 16 | \n",
- " 177 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 000 | \n",
- " 090 | \n",
- " 571542811_02 | \n",
- " 571542107_01 | \n",
- " i2 | \n",
- "
\n",
- " \n",
- " 17 | \n",
- " 177 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 179 | \n",
- " 270 | \n",
- " -571542809_01 | \n",
- " 571542809_01 | \n",
- " i2 | \n",
- "
\n",
- " \n",
- " 18 | \n",
- " 177 | \n",
- " 3 | \n",
- " A | \n",
- " 17 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " i2 | \n",
- "
\n",
- " \n",
- " 19 | \n",
- " 177 | \n",
- " 3 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " i2 | \n",
- "
\n",
- " \n",
- " 20 | \n",
- " 177 | \n",
- " 4 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 268 | \n",
- " 000 | \n",
- " -571542809_01 | \n",
- " 571542811_01 | \n",
- " i2 | \n",
- "
\n",
- " \n",
- " 21 | \n",
- " 177 | \n",
- " 4 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- " 090 | \n",
- " 180 | \n",
- " 571542107_02 | \n",
- " 571542809_01 | \n",
- " i2 | \n",
- "
\n",
- " \n",
- " 22 | \n",
- " 178 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- " 571540304_02 | \n",
- " 571556450_01 | \n",
- " i3 | \n",
- "
\n",
- " \n",
- " 23 | \n",
- " 178 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- " 571556450_02 | \n",
- " 571540304_01 | \n",
- " i3 | \n",
- "
\n",
- " \n",
- " 24 | \n",
- " 178 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 000 | \n",
- " 090 | \n",
- " 571556450_02 | \n",
- " 571500475_01 | \n",
- " i3 | \n",
- "
\n",
- " \n",
- " 25 | \n",
- " 178 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 180 | \n",
- " 270 | \n",
- " 571540304_02 | \n",
- " 571540303_01 | \n",
- " i3 | \n",
- "
\n",
- " \n",
- " 26 | \n",
- " 178 | \n",
- " 3 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 270 | \n",
- " 000 | \n",
- " 571540303_02.21 | \n",
- " 571556450_01 | \n",
- " i3 | \n",
- "
\n",
- " \n",
- " 27 | \n",
- " 178 | \n",
- " 3 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- " 571540303_02.21 | \n",
- " 571500475_01 | \n",
- " i3 | \n",
- "
\n",
- " \n",
- " 28 | \n",
- " 178 | \n",
- " 4 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- " -571500475_01 | \n",
- " 571540303_01 | \n",
- " i3 | \n",
- "
\n",
- " \n",
- " 29 | \n",
- " 178 | \n",
- " 4 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- " 090 | \n",
- " 180 | \n",
- " -571500475_01 | \n",
- " 571540304_01 | \n",
- " i3 | \n",
- "
\n",
- " \n",
- " 30 | \n",
- " 201 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- " -571500569_01 | \n",
- " 571500583_02 | \n",
- " i8 | \n",
- "
\n",
- " \n",
- " 31 | \n",
- " 201 | \n",
- " 1 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 180 | \n",
- " 270 | \n",
- " -571500569_01 | \n",
- " 571500618_01 | \n",
- " i8 | \n",
- "
\n",
- " \n",
- " 32 | \n",
- " 201 | \n",
- " 2 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 270 | \n",
- " 000 | \n",
- " 571500618_02 | \n",
- " 571500583_02 | \n",
- " i8 | \n",
- "
\n",
- " \n",
- " 33 | \n",
- " 201 | \n",
- " 2 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- " 571500618_02 | \n",
- " 571500617_01 | \n",
- " i8 | \n",
- "
\n",
- " \n",
- " 34 | \n",
- " 201 | \n",
- " 3 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- " 571500617_02 | \n",
- " 571500618_01 | \n",
- " i8 | \n",
- "
\n",
- " \n",
- " 35 | \n",
- " 201 | \n",
- " 3 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- " 571500618_02 | \n",
- " 571500617_01 | \n",
- " i8 | \n",
- "
\n",
- " \n",
- " 36 | \n",
- " 201 | \n",
- " 4 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- " 571500617_02 | \n",
- " 571500618_01 | \n",
- " i8 | \n",
- "
\n",
- " \n",
- " 37 | \n",
- " 201 | \n",
- " 4 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- " 090 | \n",
- " 180 | \n",
- " 571500617_02 | \n",
- " 571500569_01 | \n",
- " i8 | \n",
- "
\n",
- " \n",
- " 38 | \n",
- " 201 | \n",
- " 5 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 000 | \n",
- " 090 | \n",
- " 571500583_01 | \n",
- " 571500617_01 | \n",
- " i8 | \n",
- "
\n",
- " \n",
- " 39 | \n",
- " 201 | \n",
- " 5 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- " 571500583_01 | \n",
- " 571500569_01 | \n",
- " i8 | \n",
- "
\n",
- " \n",
- " 40 | \n",
- " 202 | \n",
- " 1 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- " 571510152_02 | \n",
- " -571510152_01 | \n",
- " i9 | \n",
- "
\n",
- " \n",
- " 41 | \n",
- " 202 | \n",
- " 1 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- " 571510152_01 | \n",
- " 571510152_01.65 | \n",
- " i9 | \n",
- "
\n",
- " \n",
- " 42 | \n",
- " 202 | \n",
- " 2 | \n",
- " A | \n",
- " 17 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " i9 | \n",
- "
\n",
- " \n",
- " 43 | \n",
- " 202 | \n",
- " 2 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " i9 | \n",
- "
\n",
- " \n",
- " 44 | \n",
- " 206 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- " -571511538_02 | \n",
- " 571542073_02 | \n",
- " i7 | \n",
- "
\n",
- " \n",
- " 45 | \n",
- " 206 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- " 571542073_01 | \n",
- " 571511538_02 | \n",
- " i7 | \n",
- "
\n",
- " \n",
- " 46 | \n",
- " 206 | \n",
- " 2 | \n",
- " A | \n",
- " 17 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " i7 | \n",
- "
\n",
- " \n",
- " 47 | \n",
- " 206 | \n",
- " 2 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " i7 | \n",
- "
\n",
- " \n",
- " 48 | \n",
- " 206 | \n",
- " 3 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- " -571511538_02 | \n",
- " 571542073_02 | \n",
- " i7 | \n",
- "
\n",
- " \n",
- " 49 | \n",
- " 206 | \n",
- " 3 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- " 571542073_01 | \n",
- " 571511538_02 | \n",
- " i7 | \n",
- "
\n",
- " \n",
- " 50 | \n",
- " 206 | \n",
- " 4 | \n",
- " A | \n",
- " 17 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " i7 | \n",
- "
\n",
- " \n",
- " 51 | \n",
- " 206 | \n",
- " 4 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " i7 | \n",
- "
\n",
- " \n",
- " 52 | \n",
- " 210 | \n",
- " 1 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- " -571542115_01 | \n",
- " 571500535_01 | \n",
- " i6 | \n",
- "
\n",
- " \n",
- " 53 | \n",
- " 210 | \n",
- " 1 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " i6 | \n",
- "
\n",
- " \n",
- " 54 | \n",
- " 210 | \n",
- " 2 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 268 | \n",
- " 000 | \n",
- " 571500535_02.18 | \n",
- " 571511538_01 | \n",
- " i6 | \n",
- "
\n",
- " \n",
- " 55 | \n",
- " 210 | \n",
- " 2 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- " 571500535_02.18 | \n",
- " 571542115_01 | \n",
- " i6 | \n",
- "
\n",
- " \n",
- " 56 | \n",
- " 210 | \n",
- " 3 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 359 | \n",
- " 090 | \n",
- " 571511538_02.121 | \n",
- " 571542115_01 | \n",
- " i6 | \n",
- "
\n",
- " \n",
- " 57 | \n",
- " 210 | \n",
- " 3 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- " 571511538_02.121 | \n",
- " 571500585_01 | \n",
- " i6 | \n",
- "
\n",
- " \n",
- " 58 | \n",
- " 210 | \n",
- " 4 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- " 571500585_02 | \n",
- " 571511538_01 | \n",
- " i6 | \n",
- "
\n",
- " \n",
- " 59 | \n",
- " 210 | \n",
- " 4 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 180 | \n",
- " 270 | \n",
- " 571500585_02 | \n",
- " 571500535_01 | \n",
- " i6 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
- "0 175 1 A 8 남 북 179 004 \n",
- "1 175 1 B 4 북 남 003 176 \n",
- "2 175 2 A 7 북 동 001 095 \n",
- "3 175 2 B 3 남 서 179 270 \n",
- "4 175 3 A 6 동 서 090 270 \n",
- "5 175 3 B 1 동 남 090 180 \n",
- "6 175 4 A 5 서 북 268 000 \n",
- "7 175 4 B 2 서 동 270 090 \n",
- "8 176 1 A 8 남 북 180 000 \n",
- "9 176 1 B 4 북 남 359 180 \n",
- "10 176 2 A 8 남 북 180 000 \n",
- "11 176 2 B 3 남 서 180 270 \n",
- "12 176 3 A 5 서 북 270 356 \n",
- "13 176 3 B 18 NaN NaN NaN NaN \n",
- "14 177 1 A 8 남 북 180 000 \n",
- "15 177 1 B 4 북 남 001 176 \n",
- "16 177 2 A 7 북 동 000 090 \n",
- "17 177 2 B 3 남 서 179 270 \n",
- "18 177 3 A 17 NaN NaN NaN NaN \n",
- "19 177 3 B 18 NaN NaN NaN NaN \n",
- "20 177 4 A 5 서 북 268 000 \n",
- "21 177 4 B 1 동 남 090 180 \n",
- "22 178 1 A 8 남 북 180 000 \n",
- "23 178 1 B 4 북 남 000 180 \n",
- "24 178 2 A 7 북 동 000 090 \n",
- "25 178 2 B 3 남 서 180 270 \n",
- "26 178 3 A 5 서 북 270 000 \n",
- "27 178 3 B 2 서 동 270 090 \n",
- "28 178 4 A 6 동 서 090 270 \n",
- "29 178 4 B 1 동 남 090 180 \n",
- "30 201 1 A 8 남 북 180 000 \n",
- "31 201 1 B 3 남 서 180 270 \n",
- "32 201 2 A 5 서 북 270 000 \n",
- "33 201 2 B 2 서 동 270 090 \n",
- "34 201 3 A 6 동 서 090 270 \n",
- "35 201 3 B 2 서 동 270 090 \n",
- "36 201 4 A 6 동 서 090 270 \n",
- "37 201 4 B 1 동 남 090 180 \n",
- "38 201 5 A 7 북 동 000 090 \n",
- "39 201 5 B 4 북 남 000 180 \n",
- "40 202 1 A 6 동 서 090 270 \n",
- "41 202 1 B 2 서 동 270 090 \n",
- "42 202 2 A 17 NaN NaN NaN NaN \n",
- "43 202 2 B 18 NaN NaN NaN NaN \n",
- "44 206 1 A 8 남 북 180 000 \n",
- "45 206 1 B 4 북 남 000 180 \n",
- "46 206 2 A 17 NaN NaN NaN NaN \n",
- "47 206 2 B 18 NaN NaN NaN NaN \n",
- "48 206 3 A 8 남 북 180 000 \n",
- "49 206 3 B 4 북 남 000 180 \n",
- "50 206 4 A 17 NaN NaN NaN NaN \n",
- "51 206 4 B 18 NaN NaN NaN NaN \n",
- "52 210 1 A 6 동 서 090 270 \n",
- "53 210 1 B 18 NaN NaN NaN NaN \n",
- "54 210 2 A 5 서 북 268 000 \n",
- "55 210 2 B 2 서 동 270 090 \n",
- "56 210 3 A 7 북 동 359 090 \n",
- "57 210 3 B 4 북 남 000 180 \n",
- "58 210 4 A 8 남 북 180 000 \n",
- "59 210 4 B 3 남 서 180 270 \n",
- "\n",
- " inc_edge out_edge node_id \n",
- "0 -571542797_02 571500487_01 i0 \n",
- "1 -571500487_01 571542797_02 i0 \n",
- "2 -571500487_01 571545870_01 i0 \n",
- "3 -571542797_02 571510153_01 i0 \n",
- "4 571545870_02 571510153_01 i0 \n",
- "5 571545870_02 571542797_02 i0 \n",
- "6 571510153_02 571500487_01 i0 \n",
- "7 571510153_02 571545870_01 i0 \n",
- "8 -571542810_01 -571542797_02.99 i1 \n",
- "9 571542797_02.99 571542810_01 i1 \n",
- "10 -571542810_01 -571542797_02.99 i1 \n",
- "11 -571542810_01 571543469_01 i1 \n",
- "12 571543469_02 -571542797_02.99 i1 \n",
- "13 NaN NaN i1 \n",
- "14 -571542809_01 571542811_01 i2 \n",
- "15 571542811_02 571542809_01 i2 \n",
- "16 571542811_02 571542107_01 i2 \n",
- "17 -571542809_01 571542809_01 i2 \n",
- "18 NaN NaN i2 \n",
- "19 NaN NaN i2 \n",
- "20 -571542809_01 571542811_01 i2 \n",
- "21 571542107_02 571542809_01 i2 \n",
- "22 571540304_02 571556450_01 i3 \n",
- "23 571556450_02 571540304_01 i3 \n",
- "24 571556450_02 571500475_01 i3 \n",
- "25 571540304_02 571540303_01 i3 \n",
- "26 571540303_02.21 571556450_01 i3 \n",
- "27 571540303_02.21 571500475_01 i3 \n",
- "28 -571500475_01 571540303_01 i3 \n",
- "29 -571500475_01 571540304_01 i3 \n",
- "30 -571500569_01 571500583_02 i8 \n",
- "31 -571500569_01 571500618_01 i8 \n",
- "32 571500618_02 571500583_02 i8 \n",
- "33 571500618_02 571500617_01 i8 \n",
- "34 571500617_02 571500618_01 i8 \n",
- "35 571500618_02 571500617_01 i8 \n",
- "36 571500617_02 571500618_01 i8 \n",
- "37 571500617_02 571500569_01 i8 \n",
- "38 571500583_01 571500617_01 i8 \n",
- "39 571500583_01 571500569_01 i8 \n",
- "40 571510152_02 -571510152_01 i9 \n",
- "41 571510152_01 571510152_01.65 i9 \n",
- "42 NaN NaN i9 \n",
- "43 NaN NaN i9 \n",
- "44 -571511538_02 571542073_02 i7 \n",
- "45 571542073_01 571511538_02 i7 \n",
- "46 NaN NaN i7 \n",
- "47 NaN NaN i7 \n",
- "48 -571511538_02 571542073_02 i7 \n",
- "49 571542073_01 571511538_02 i7 \n",
- "50 NaN NaN i7 \n",
- "51 NaN NaN i7 \n",
- "52 -571542115_01 571500535_01 i6 \n",
- "53 NaN NaN i6 \n",
- "54 571500535_02.18 571511538_01 i6 \n",
- "55 571500535_02.18 571542115_01 i6 \n",
- "56 571511538_02.121 571542115_01 i6 \n",
- "57 571511538_02.121 571500585_01 i6 \n",
- "58 571500585_02 571511538_01 i6 \n",
- "59 571500585_02 571500535_01 i6 "
- ]
- },
- "execution_count": 6,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# [네트워크], [교차로-노드 매칭], [교차로정보] 불러오기\n",
- "net = sumolib.net.readNet('../../Data/networks/SN_sample.net.xml')\n",
- "inter_node = pd.read_csv('../../Data/tables/inter_node.csv', index_col=0)\n",
- "inter_info = pd.read_csv('../../Data/tables/inter_info.csv', index_col=0)\n",
- "\n",
- "inter_node1 = inter_node[inter_node.inter_type == 'parent'].drop('inter_type', axis=1)\n",
- "inter_info1 = inter_info[['inter_no', 'inter_lat', 'inter_lon']]\n",
- "inter = pd.merge(inter_node1, inter_info1, how='left', left_on=['inter_no'],\n",
- " right_on=['inter_no']).drop_duplicates()\n",
- "\n",
- "inter2node = dict(zip(inter['inter_no'], inter['node_id']))\n",
- "\n",
- "match5 = match4.copy()\n",
- "# 진입진출ID 매칭\n",
- "for index, row in match5.iterrows():\n",
- " node_id = inter2node[row.inter_no]\n",
- " node = net.getNode(node_id)\n",
- " # 교차로의 모든 (from / to) edges\n",
- " inc_edges = [edge for edge in node.getIncoming() if edge.getFunction() == ''] # incoming edges\n",
- " out_edges = [edge for edge in node.getOutgoing() if edge.getFunction() == ''] # outgoing edges\n",
- " # 교차로의 모든 (from / to) directions\n",
- " inc_dirs = []\n",
- " for inc_edge in inc_edges:\n",
- " start = inc_edge.getShape()[-2]\n",
- " end = inc_edge.getShape()[-1]\n",
- " inc_dir = np.array(end) - np.array(start)\n",
- " inc_dir = inc_dir / (inc_dir ** 2).sum() ** 0.5\n",
- " inc_dirs.append(inc_dir)\n",
- " out_dirs = []\n",
- " for out_edge in out_edges:\n",
- " start = out_edge.getShape()[0]\n",
- " end = out_edge.getShape()[1]\n",
- " out_dir = np.array(end) - np.array(start)\n",
- " out_dir = out_dir / (out_dir ** 2).sum() ** 0.5\n",
- " out_dirs.append(out_dir)\n",
- " # 진입각, 진출각 불러오기\n",
- " if not pd.isna(row.inc_angle):\n",
- " inc_angle = int(row.inc_angle)\n",
- " out_angle = int(row.out_angle)\n",
- " # 방위각을 일반각으로 가공, 라디안 변환, 단위벡터로 변환\n",
- " inc_angle = (-90 - inc_angle) % 360\n",
- " inc_angle = inc_angle * np.pi / 180.\n",
- " inc_dir_true = np.array([np.cos(inc_angle), np.sin(inc_angle)])\n",
- " out_angle = (90 - out_angle) % 360\n",
- " out_angle = out_angle * np.pi / 180.\n",
- " out_dir_true = np.array([np.cos(out_angle), np.sin(out_angle)])\n",
- " # 매칭 엣지 반환\n",
- " inc_index = np.array([np.dot(inc_dir, inc_dir_true) for inc_dir in inc_dirs]).argmax()\n",
- " out_index = np.array([np.dot(out_dir, out_dir_true) for out_dir in out_dirs]).argmax()\n",
- " inc_edge_id = inc_edges[inc_index].getID()\n",
- " out_edge_id = out_edges[out_index].getID()\n",
- " match5.at[index, 'inc_edge'] = inc_edge_id\n",
- " match5.at[index, 'out_edge'] = out_edge_id\n",
- "match5['node_id'] = match5['inter_no'].map(inter2node)\n",
- "match5 = match5.sort_values(by=['inter_no','phase_no','ring_type']).reset_index(drop=True)\n",
- "match5"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array(['u00', 'u20', 'u30', 'u31', 'u32', 'u60'], dtype=object)"
- ]
- },
- "execution_count": 7,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 유턴/연동교차로에 대하여 진입ID, 진출ID 부여\n",
- "node2inter = dict(zip(inter_node['node_id'], inter_node['inter_no']))\n",
- "\n",
- "uturn = pd.read_csv('../../Data/tables/child_uturn.csv')\n",
- "coord = pd.read_csv('../../Data/tables/child_coord.csv')\n",
- "\n",
- "child_ids = inter_node[inter_node.inter_type=='child'].node_id.unique()\n",
- "ch2pa = {} # child to parent\n",
- "for child_id in child_ids:\n",
- " parent_no = inter_node[inter_node.node_id==child_id].inter_no.iloc[0]\n",
- " sub_inter_node = inter_node[inter_node.inter_no==parent_no]\n",
- " ch2pa[child_id] = sub_inter_node[sub_inter_node.inter_type=='parent'].iloc[0].node_id\n",
- "directions = ['북', '북동', '동', '남동', '남', '남서', '서', '북서'] # 정북기준 시계방향으로 8방향\n",
- "u_ids = uturn.child_id.unique()\n",
- "u_ids"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "u00 i0 좌회전시 북\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phase_no | \n",
- " ring_type | \n",
- " move_no | \n",
- " inc_dir | \n",
- " out_dir | \n",
- " inc_angle | \n",
- " out_angle | \n",
- " inc_edge | \n",
- " out_edge | \n",
- " node_id | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 175 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 179 | \n",
- " 004 | \n",
- " NaN | \n",
- " NaN | \n",
- " u00 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 175 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 003 | \n",
- " 176 | \n",
- " NaN | \n",
- " NaN | \n",
- " u00 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 175 | \n",
- " 2 | \n",
- " A | \n",
- " 19 | \n",
- " 북 | \n",
- " 동 | \n",
- " 001 | \n",
- " 095 | \n",
- " 571500487_02 | \n",
- " 571500487_01.32 | \n",
- " u00 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 175 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 179 | \n",
- " 270 | \n",
- " NaN | \n",
- " NaN | \n",
- " u00 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 175 | \n",
- " 3 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- " NaN | \n",
- " NaN | \n",
- " u00 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 175 | \n",
- " 3 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- " 090 | \n",
- " 180 | \n",
- " NaN | \n",
- " NaN | \n",
- " u00 | \n",
- "
\n",
- " \n",
- " 6 | \n",
- " 175 | \n",
- " 4 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 268 | \n",
- " 000 | \n",
- " NaN | \n",
- " NaN | \n",
- " u00 | \n",
- "
\n",
- " \n",
- " 7 | \n",
- " 175 | \n",
- " 4 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- " NaN | \n",
- " NaN | \n",
- " u00 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
- "0 175 1 A 8 남 북 179 004 \n",
- "1 175 1 B 4 북 남 003 176 \n",
- "2 175 2 A 19 북 동 001 095 \n",
- "3 175 2 B 3 남 서 179 270 \n",
- "4 175 3 A 6 동 서 090 270 \n",
- "5 175 3 B 1 동 남 090 180 \n",
- "6 175 4 A 5 서 북 268 000 \n",
- "7 175 4 B 2 서 동 270 090 \n",
- "\n",
- " inc_edge out_edge node_id \n",
- "0 NaN NaN u00 \n",
- "1 NaN NaN u00 \n",
- "2 571500487_02 571500487_01.32 u00 \n",
- "3 NaN NaN u00 \n",
- "4 NaN NaN u00 \n",
- "5 NaN NaN u00 \n",
- "6 NaN NaN u00 \n",
- "7 NaN NaN u00 "
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "u20 i2 보행신호시 북\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phase_no | \n",
- " ring_type | \n",
- " move_no | \n",
- " inc_dir | \n",
- " out_dir | \n",
- " inc_angle | \n",
- " out_angle | \n",
- " inc_edge | \n",
- " out_edge | \n",
- " node_id | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 177 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- " NaN | \n",
- " NaN | \n",
- " u20 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 177 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 001 | \n",
- " 176 | \n",
- " NaN | \n",
- " NaN | \n",
- " u20 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 177 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 000 | \n",
- " 090 | \n",
- " NaN | \n",
- " NaN | \n",
- " u20 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 177 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 179 | \n",
- " 270 | \n",
- " NaN | \n",
- " NaN | \n",
- " u20 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 177 | \n",
- " 3 | \n",
- " A | \n",
- " 17 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " 571542810_01.51 | \n",
- " 571542810_02 | \n",
- " u20 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 177 | \n",
- " 3 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " u20 | \n",
- "
\n",
- " \n",
- " 6 | \n",
- " 177 | \n",
- " 4 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 268 | \n",
- " 000 | \n",
- " NaN | \n",
- " NaN | \n",
- " u20 | \n",
- "
\n",
- " \n",
- " 7 | \n",
- " 177 | \n",
- " 4 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- " 090 | \n",
- " 180 | \n",
- " NaN | \n",
- " NaN | \n",
- " u20 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
- "0 177 1 A 8 남 북 180 000 \n",
- "1 177 1 B 4 북 남 001 176 \n",
- "2 177 2 A 7 북 동 000 090 \n",
- "3 177 2 B 3 남 서 179 270 \n",
- "4 177 3 A 17 NaN NaN NaN NaN \n",
- "5 177 3 B 18 NaN NaN NaN NaN \n",
- "6 177 4 A 5 서 북 268 000 \n",
- "7 177 4 B 1 동 남 090 180 \n",
- "\n",
- " inc_edge out_edge node_id \n",
- "0 NaN NaN u20 \n",
- "1 NaN NaN u20 \n",
- "2 NaN NaN u20 \n",
- "3 NaN NaN u20 \n",
- "4 571542810_01.51 571542810_02 u20 \n",
- "5 NaN NaN u20 \n",
- "6 NaN NaN u20 \n",
- "7 NaN NaN u20 "
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "u30 i3 보행신호시 북\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phase_no | \n",
- " ring_type | \n",
- " move_no | \n",
- " inc_dir | \n",
- " out_dir | \n",
- " inc_angle | \n",
- " out_angle | \n",
- " inc_edge | \n",
- " out_edge | \n",
- " node_id | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 178 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- " NaN | \n",
- " NaN | \n",
- " u30 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 178 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- " NaN | \n",
- " NaN | \n",
- " u30 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 178 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 000 | \n",
- " 090 | \n",
- " NaN | \n",
- " NaN | \n",
- " u30 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 178 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 180 | \n",
- " 270 | \n",
- " NaN | \n",
- " NaN | \n",
- " u30 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 178 | \n",
- " 3 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 270 | \n",
- " 000 | \n",
- " NaN | \n",
- " NaN | \n",
- " u30 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 178 | \n",
- " 3 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- " NaN | \n",
- " NaN | \n",
- " u30 | \n",
- "
\n",
- " \n",
- " 6 | \n",
- " 178 | \n",
- " 4 | \n",
- " A | \n",
- " 19 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- " 571556452_01 | \n",
- " 571556452_02 | \n",
- " u30 | \n",
- "
\n",
- " \n",
- " 7 | \n",
- " 178 | \n",
- " 4 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- " 090 | \n",
- " 180 | \n",
- " NaN | \n",
- " NaN | \n",
- " u30 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
- "0 178 1 A 8 남 북 180 000 \n",
- "1 178 1 B 4 북 남 000 180 \n",
- "2 178 2 A 7 북 동 000 090 \n",
- "3 178 2 B 3 남 서 180 270 \n",
- "4 178 3 A 5 서 북 270 000 \n",
- "5 178 3 B 2 서 동 270 090 \n",
- "6 178 4 A 19 동 서 090 270 \n",
- "7 178 4 B 1 동 남 090 180 \n",
- "\n",
- " inc_edge out_edge node_id \n",
- "0 NaN NaN u30 \n",
- "1 NaN NaN u30 \n",
- "2 NaN NaN u30 \n",
- "3 NaN NaN u30 \n",
- "4 NaN NaN u30 \n",
- "5 NaN NaN u30 \n",
- "6 571556452_01 571556452_02 u30 \n",
- "7 NaN NaN u30 "
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "u31 i3 보행신호시 동\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phase_no | \n",
- " ring_type | \n",
- " move_no | \n",
- " inc_dir | \n",
- " out_dir | \n",
- " inc_angle | \n",
- " out_angle | \n",
- " inc_edge | \n",
- " out_edge | \n",
- " node_id | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 178 | \n",
- " 1 | \n",
- " A | \n",
- " 19 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- " 571500475_02 | \n",
- " 571500475_01.26 | \n",
- " u31 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 178 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- " NaN | \n",
- " NaN | \n",
- " u31 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 178 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 000 | \n",
- " 090 | \n",
- " NaN | \n",
- " NaN | \n",
- " u31 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 178 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 180 | \n",
- " 270 | \n",
- " NaN | \n",
- " NaN | \n",
- " u31 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 178 | \n",
- " 3 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 270 | \n",
- " 000 | \n",
- " NaN | \n",
- " NaN | \n",
- " u31 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 178 | \n",
- " 3 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- " NaN | \n",
- " NaN | \n",
- " u31 | \n",
- "
\n",
- " \n",
- " 6 | \n",
- " 178 | \n",
- " 4 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- " NaN | \n",
- " NaN | \n",
- " u31 | \n",
- "
\n",
- " \n",
- " 7 | \n",
- " 178 | \n",
- " 4 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- " 090 | \n",
- " 180 | \n",
- " NaN | \n",
- " NaN | \n",
- " u31 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
- "0 178 1 A 19 남 북 180 000 \n",
- "1 178 1 B 4 북 남 000 180 \n",
- "2 178 2 A 7 북 동 000 090 \n",
- "3 178 2 B 3 남 서 180 270 \n",
- "4 178 3 A 5 서 북 270 000 \n",
- "5 178 3 B 2 서 동 270 090 \n",
- "6 178 4 A 6 동 서 090 270 \n",
- "7 178 4 B 1 동 남 090 180 \n",
- "\n",
- " inc_edge out_edge node_id \n",
- "0 571500475_02 571500475_01.26 u31 \n",
- "1 NaN NaN u31 \n",
- "2 NaN NaN u31 \n",
- "3 NaN NaN u31 \n",
- "4 NaN NaN u31 \n",
- "5 NaN NaN u31 \n",
- "6 NaN NaN u31 \n",
- "7 NaN NaN u31 "
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "u32 i3 보행신호시 서\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phase_no | \n",
- " ring_type | \n",
- " move_no | \n",
- " inc_dir | \n",
- " out_dir | \n",
- " inc_angle | \n",
- " out_angle | \n",
- " inc_edge | \n",
- " out_edge | \n",
- " node_id | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 178 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- " NaN | \n",
- " NaN | \n",
- " u32 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 178 | \n",
- " 1 | \n",
- " B | \n",
- " 19 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- " 571540303_02 | \n",
- " -571540303_02 | \n",
- " u32 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 178 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 000 | \n",
- " 090 | \n",
- " NaN | \n",
- " NaN | \n",
- " u32 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 178 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 180 | \n",
- " 270 | \n",
- " NaN | \n",
- " NaN | \n",
- " u32 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 178 | \n",
- " 3 | \n",
- " A | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 270 | \n",
- " 000 | \n",
- " NaN | \n",
- " NaN | \n",
- " u32 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 178 | \n",
- " 3 | \n",
- " B | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- " NaN | \n",
- " NaN | \n",
- " u32 | \n",
- "
\n",
- " \n",
- " 6 | \n",
- " 178 | \n",
- " 4 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- " NaN | \n",
- " NaN | \n",
- " u32 | \n",
- "
\n",
- " \n",
- " 7 | \n",
- " 178 | \n",
- " 4 | \n",
- " B | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- " 090 | \n",
- " 180 | \n",
- " NaN | \n",
- " NaN | \n",
- " u32 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
- "0 178 1 A 8 남 북 180 000 \n",
- "1 178 1 B 19 북 남 000 180 \n",
- "2 178 2 A 7 북 동 000 090 \n",
- "3 178 2 B 3 남 서 180 270 \n",
- "4 178 3 A 5 서 북 270 000 \n",
- "5 178 3 B 2 서 동 270 090 \n",
- "6 178 4 A 6 동 서 090 270 \n",
- "7 178 4 B 1 동 남 090 180 \n",
- "\n",
- " inc_edge out_edge node_id \n",
- "0 NaN NaN u32 \n",
- "1 571540303_02 -571540303_02 u32 \n",
- "2 NaN NaN u32 \n",
- "3 NaN NaN u32 \n",
- "4 NaN NaN u32 \n",
- "5 NaN NaN u32 \n",
- "6 NaN NaN u32 \n",
- "7 NaN NaN u32 "
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "u60 i6 직좌시 서\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phase_no | \n",
- " ring_type | \n",
- " move_no | \n",
- " inc_dir | \n",
- " out_dir | \n",
- " inc_angle | \n",
- " out_angle | \n",
- " inc_edge | \n",
- " out_edge | \n",
- " node_id | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 210 | \n",
- " 1 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- " NaN | \n",
- " NaN | \n",
- " u60 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 210 | \n",
- " 1 | \n",
- " B | \n",
- " 18 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " u60 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 210 | \n",
- " 2 | \n",
- " A | \n",
- " 19 | \n",
- " 서 | \n",
- " 북 | \n",
- " 268 | \n",
- " 000 | \n",
- " 571500535_02 | \n",
- " -571500535_02 | \n",
- " u60 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 210 | \n",
- " 2 | \n",
- " B | \n",
- " 19 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- " 571500535_02 | \n",
- " -571500535_02 | \n",
- " u60 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 210 | \n",
- " 3 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 359 | \n",
- " 090 | \n",
- " NaN | \n",
- " NaN | \n",
- " u60 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 210 | \n",
- " 3 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- " NaN | \n",
- " NaN | \n",
- " u60 | \n",
- "
\n",
- " \n",
- " 6 | \n",
- " 210 | \n",
- " 4 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- " NaN | \n",
- " NaN | \n",
- " u60 | \n",
- "
\n",
- " \n",
- " 7 | \n",
- " 210 | \n",
- " 4 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 180 | \n",
- " 270 | \n",
- " NaN | \n",
- " NaN | \n",
- " u60 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
- "0 210 1 A 6 동 서 090 270 \n",
- "1 210 1 B 18 NaN NaN NaN NaN \n",
- "2 210 2 A 19 서 북 268 000 \n",
- "3 210 2 B 19 서 동 270 090 \n",
- "4 210 3 A 7 북 동 359 090 \n",
- "5 210 3 B 4 북 남 000 180 \n",
- "6 210 4 A 8 남 북 180 000 \n",
- "7 210 4 B 3 남 서 180 270 \n",
- "\n",
- " inc_edge out_edge node_id \n",
- "0 NaN NaN u60 \n",
- "1 NaN NaN u60 \n",
- "2 571500535_02 -571500535_02 u60 \n",
- "3 571500535_02 -571500535_02 u60 \n",
- "4 NaN NaN u60 \n",
- "5 NaN NaN u60 \n",
- "6 NaN NaN u60 \n",
- "7 NaN NaN u60 "
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phase_no | \n",
- " ring_type | \n",
- " move_no | \n",
- " inc_dir | \n",
- " out_dir | \n",
- " inc_angle | \n",
- " out_angle | \n",
- " inc_edge | \n",
- " out_edge | \n",
- " node_id | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 178 | \n",
- " 1 | \n",
- " A | \n",
- " 20 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " c30 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 178 | \n",
- " 1 | \n",
- " B | \n",
- " 20 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " c30 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 178 | \n",
- " 2 | \n",
- " A | \n",
- " 20 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " 571542116_01 | \n",
- " -571542116_02.96 | \n",
- " c30 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 178 | \n",
- " 2 | \n",
- " B | \n",
- " 20 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " 571542116_02.96 | \n",
- " 571542116_02.164 | \n",
- " c30 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 178 | \n",
- " 3 | \n",
- " A | \n",
- " 20 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " 571542116_01 | \n",
- " -571542116_02.96 | \n",
- " c30 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 178 | \n",
- " 3 | \n",
- " B | \n",
- " 20 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " 571542116_02.96 | \n",
- " 571542116_02.164 | \n",
- " c30 | \n",
- "
\n",
- " \n",
- " 6 | \n",
- " 178 | \n",
- " 4 | \n",
- " A | \n",
- " 20 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " 571542116_01 | \n",
- " -571542116_02.96 | \n",
- " c30 | \n",
- "
\n",
- " \n",
- " 7 | \n",
- " 178 | \n",
- " 4 | \n",
- " B | \n",
- " 20 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " 571542116_02.96 | \n",
- " 571542116_02.164 | \n",
- " c30 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle \\\n",
- "0 178 1 A 20 NaN NaN NaN \n",
- "1 178 1 B 20 NaN NaN NaN \n",
- "2 178 2 A 20 NaN NaN NaN \n",
- "3 178 2 B 20 NaN NaN NaN \n",
- "4 178 3 A 20 NaN NaN NaN \n",
- "5 178 3 B 20 NaN NaN NaN \n",
- "6 178 4 A 20 NaN NaN NaN \n",
- "7 178 4 B 20 NaN NaN NaN \n",
- "\n",
- " out_angle inc_edge out_edge node_id \n",
- "0 NaN NaN NaN c30 \n",
- "1 NaN NaN NaN c30 \n",
- "2 NaN 571542116_01 -571542116_02.96 c30 \n",
- "3 NaN 571542116_02.96 571542116_02.164 c30 \n",
- "4 NaN 571542116_01 -571542116_02.96 c30 \n",
- "5 NaN 571542116_02.96 571542116_02.164 c30 \n",
- "6 NaN 571542116_01 -571542116_02.96 c30 \n",
- "7 NaN 571542116_02.96 571542116_02.164 c30 "
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phase_no | \n",
- " ring_type | \n",
- " move_no | \n",
- " inc_dir | \n",
- " out_dir | \n",
- " inc_angle | \n",
- " out_angle | \n",
- " inc_edge | \n",
- " out_edge | \n",
- " node_id | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 175 | \n",
- " 1 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 179 | \n",
- " 004 | \n",
- " -571542797_02 | \n",
- " 571500487_01 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 175 | \n",
- " 1 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 003 | \n",
- " 176 | \n",
- " -571500487_01 | \n",
- " 571542797_02 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 175 | \n",
- " 2 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 001 | \n",
- " 095 | \n",
- " -571500487_01 | \n",
- " 571545870_01 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 175 | \n",
- " 2 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 179 | \n",
- " 270 | \n",
- " -571542797_02 | \n",
- " 571510153_01 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 175 | \n",
- " 3 | \n",
- " A | \n",
- " 6 | \n",
- " 동 | \n",
- " 서 | \n",
- " 090 | \n",
- " 270 | \n",
- " 571545870_02 | \n",
- " 571510153_01 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 210 | \n",
- " 2 | \n",
- " B | \n",
- " 19 | \n",
- " 서 | \n",
- " 동 | \n",
- " 270 | \n",
- " 090 | \n",
- " 571500535_02 | \n",
- " -571500535_02 | \n",
- " u60 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 210 | \n",
- " 3 | \n",
- " A | \n",
- " 7 | \n",
- " 북 | \n",
- " 동 | \n",
- " 359 | \n",
- " 090 | \n",
- " NaN | \n",
- " NaN | \n",
- " u60 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 210 | \n",
- " 3 | \n",
- " B | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " 000 | \n",
- " 180 | \n",
- " NaN | \n",
- " NaN | \n",
- " u60 | \n",
- "
\n",
- " \n",
- " 6 | \n",
- " 210 | \n",
- " 4 | \n",
- " A | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 180 | \n",
- " 000 | \n",
- " NaN | \n",
- " NaN | \n",
- " u60 | \n",
- "
\n",
- " \n",
- " 7 | \n",
- " 210 | \n",
- " 4 | \n",
- " B | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " 180 | \n",
- " 270 | \n",
- " NaN | \n",
- " NaN | \n",
- " u60 | \n",
- "
\n",
- " \n",
- "
\n",
- "
116 rows × 11 columns
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phase_no ring_type move_no inc_dir out_dir inc_angle out_angle \\\n",
- "0 175 1 A 8 남 북 179 004 \n",
- "1 175 1 B 4 북 남 003 176 \n",
- "2 175 2 A 7 북 동 001 095 \n",
- "3 175 2 B 3 남 서 179 270 \n",
- "4 175 3 A 6 동 서 090 270 \n",
- ".. ... ... ... ... ... ... ... ... \n",
- "3 210 2 B 19 서 동 270 090 \n",
- "4 210 3 A 7 북 동 359 090 \n",
- "5 210 3 B 4 북 남 000 180 \n",
- "6 210 4 A 8 남 북 180 000 \n",
- "7 210 4 B 3 남 서 180 270 \n",
- "\n",
- " inc_edge out_edge node_id \n",
- "0 -571542797_02 571500487_01 i0 \n",
- "1 -571500487_01 571542797_02 i0 \n",
- "2 -571500487_01 571545870_01 i0 \n",
- "3 -571542797_02 571510153_01 i0 \n",
- "4 571545870_02 571510153_01 i0 \n",
- ".. ... ... ... \n",
- "3 571500535_02 -571500535_02 u60 \n",
- "4 NaN NaN u60 \n",
- "5 NaN NaN u60 \n",
- "6 NaN NaN u60 \n",
- "7 NaN NaN u60 \n",
- "\n",
- "[116 rows x 11 columns]"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "# 유턴/연동교차로에 대하여 진입ID, 진출ID 부여\n",
- "node2inter = dict(zip(inter_node['node_id'], inter_node['inter_no']))\n",
- "\n",
- "uturn = pd.read_csv('../../Data/tables/child_uturn.csv')\n",
- "coord = pd.read_csv('../../Data/tables/child_coord.csv')\n",
- "child_ids = inter_node[inter_node.inter_type=='child'].node_id.unique()\n",
- "ch2pa = {} # child to parent\n",
- "for child_id in child_ids:\n",
- " parent_no = inter_node[inter_node.node_id==child_id].inter_no.iloc[0]\n",
- " sub_inter_node = inter_node[inter_node.inter_no==parent_no]\n",
- " ch2pa[child_id] = sub_inter_node[sub_inter_node.inter_type=='parent'].iloc[0].node_id\n",
- "directions = ['북', '북동', '동', '남동', '남', '남서', '서', '북서'] # 정북기준 시계방향으로 8방향\n",
- "u_ids = uturn.child_id.unique()\n",
- "# 각 child uturn node에 대하여 (inc_edge_id, out_edge_id) 부여\n",
- "cmatches = []\n",
- "for _, row in uturn.iterrows():\n",
- " child_id = row.child_id\n",
- " parent_id = row.parent_id\n",
- " direction = row.direction\n",
- " condition = row.condition\n",
- " inc_edge_id = row.inc_edge\n",
- " out_edge_id = row.out_edge\n",
- " ind = directions.index(direction)\n",
- " if condition == \"좌회전시\":\n",
- " print(child_id, parent_id, condition, direction)\n",
- " inc_dire = direction\n",
- " out_dire_A = out_dire_B = directions[(ind + 2) % len(directions)]\n",
- " elif condition == \"직진시\":\n",
- " print(child_id, parent_id, condition, direction)\n",
- " inc_dire = direction\n",
- " out_dire_A = out_dire_B = directions[(ind + 4) % len(directions)]\n",
- " elif condition == \"직좌시\":\n",
- " print(child_id, parent_id, condition, direction)\n",
- " inc_dire = direction\n",
- " out_dire_A = directions[(ind + 2) % len(directions)]\n",
- " out_dire_B = directions[(ind + 4) % len(directions)]\n",
- " elif condition == \"보행신호시\":\n",
- " print(child_id, parent_id, condition, direction)\n",
- " inc_dire = directions[(ind + 2) % len(directions)]\n",
- " out_dire_A = directions[(ind - 2) % len(directions)]\n",
- " out_dire_B = directions[(ind - 2) % len(directions)]\n",
- " cmatch = match5.copy()[match5.node_id==parent_id] # match dataframe for a child node\n",
- " cmatch = cmatch.sort_values(by=['phase_no', 'ring_type']).reset_index(drop=True)\n",
- " cmatch['node_id'] = child_id\n",
- " cmatch[['inc_edge', 'out_edge']] = np.nan\n",
- " if condition == '직좌시':\n",
- " ap = cmatch[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A)].phase_no.iloc[0]\n",
- " bp = cmatch[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B)].phase_no.iloc[0]\n",
- " # 직진과 좌회전이 같은 현시에 있는 경우에만 (inc_edge_id, out_edge_id)를 부여한다.\n",
- " if ap == bp:\n",
- " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
- " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
- " elif condition == '보행신호시':\n",
- " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
- " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
- " # 이동류번호가 17(보행신호)이면서 유턴노드방향으로 가는 신호가 없으면 (inc_edge_id, out_edge_id)를 부여한다.\n",
- " cmatch.loc[(cmatch.move_no==17) & (cmatch.out_dir!=direction), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
- " else:\n",
- " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
- " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
- " # 유턴신호의 이동류번호를 19로 부여한다.\n",
- " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), 'move_no'] = 19\n",
- " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), 'move_no'] = 19\n",
- " display(cmatch)\n",
- " cmatches.append(cmatch)\n",
- "\n",
- "# 각 child coordination node에 대하여 (inc_edge_id, out_edge_id) 부여\n",
- "coord['inter_no'] = coord['parent_id'].map(node2inter)\n",
- "coord = coord.rename(columns={'child_id':'node_id'})\n",
- "coord[['inc_dir', 'out_dir', 'inc_angle','out_angle']] = np.nan\n",
- "coord['move_no'] = 20\n",
- "coord = coord[['inter_no', 'phase_no', 'ring_type', 'move_no', 'inc_dir', 'out_dir', 'inc_angle','out_angle', 'inc_edge', 'out_edge', 'node_id']]\n",
- "# display(coord)\n",
- "cmatches = pd.concat(cmatches)\n",
- "display(coord)\n",
- "match6 = pd.concat([match5, cmatches, coord]).drop_duplicates().sort_values(by=['inter_no', 'node_id', 'phase_no', 'ring_type'])\n",
- "# with pd.option_context('display.max_rows', None, 'display.max_columns', None):\n",
- "match6.to_csv('../../Data/tables/matching/match6.csv')\n",
- "display(match6)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " move_no | \n",
- " inc_dir | \n",
- " out_dir | \n",
- " inc_edge | \n",
- " out_edge | \n",
- " node_id | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 175 | \n",
- " 1 | \n",
- " 동 | \n",
- " 남 | \n",
- " 571545870_02 | \n",
- " 571542797_02 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 175 | \n",
- " 2 | \n",
- " 서 | \n",
- " 동 | \n",
- " 571510153_02 | \n",
- " 571545870_01 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 175 | \n",
- " 3 | \n",
- " 남 | \n",
- " 서 | \n",
- " -571542797_02 | \n",
- " 571510153_01 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 175 | \n",
- " 4 | \n",
- " 북 | \n",
- " 남 | \n",
- " -571500487_01 | \n",
- " 571542797_02 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 175 | \n",
- " 5 | \n",
- " 서 | \n",
- " 북 | \n",
- " 571510153_02 | \n",
- " 571500487_01 | \n",
- " i0 | \n",
- "
\n",
- " \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- "
\n",
- " \n",
- " 69 | \n",
- " 210 | \n",
- " 8 | \n",
- " 남 | \n",
- " 북 | \n",
- " 571500585_02 | \n",
- " 571511538_01 | \n",
- " i6 | \n",
- "
\n",
- " \n",
- " 70 | \n",
- " 210 | \n",
- " 21 | \n",
- " 북 | \n",
- " 서 | \n",
- " 571511538_02.121 | \n",
- " 571500535_01 | \n",
- " i6 | \n",
- "
\n",
- " \n",
- " 71 | \n",
- " 210 | \n",
- " 21 | \n",
- " 서 | \n",
- " 남 | \n",
- " 571500535_02.18 | \n",
- " 571500585_01 | \n",
- " i6 | \n",
- "
\n",
- " \n",
- " 72 | \n",
- " 210 | \n",
- " 21 | \n",
- " 남 | \n",
- " 동 | \n",
- " 571500585_02 | \n",
- " 571542115_01 | \n",
- " i6 | \n",
- "
\n",
- " \n",
- " 73 | \n",
- " 210 | \n",
- " 21 | \n",
- " 동 | \n",
- " 북 | \n",
- " -571542115_01 | \n",
- " 571511538_01 | \n",
- " i6 | \n",
- "
\n",
- " \n",
- "
\n",
- "
74 rows × 7 columns
\n",
- "
"
- ],
- "text/plain": [
- " inter_no move_no inc_dir out_dir inc_edge out_edge node_id\n",
- "0 175 1 동 남 571545870_02 571542797_02 i0\n",
- "1 175 2 서 동 571510153_02 571545870_01 i0\n",
- "2 175 3 남 서 -571542797_02 571510153_01 i0\n",
- "3 175 4 북 남 -571500487_01 571542797_02 i0\n",
- "4 175 5 서 북 571510153_02 571500487_01 i0\n",
- ".. ... ... ... ... ... ... ...\n",
- "69 210 8 남 북 571500585_02 571511538_01 i6\n",
- "70 210 21 북 서 571511538_02.121 571500535_01 i6\n",
- "71 210 21 서 남 571500535_02.18 571500585_01 i6\n",
- "72 210 21 남 동 571500585_02 571542115_01 i6\n",
- "73 210 21 동 북 -571542115_01 571511538_01 i6\n",
- "\n",
- "[74 rows x 7 columns]"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "# 이동류 매칭\n",
- "# 각 교차로에 대하여, 가능한 모든 이동류(1~18, 21)에 대한 진입·진출엣지ID를 지정한다.\n",
- "# 모든 이동류에 대해 지정하므로, 시차제시 이전과 다른 이동류가 등장하더라도 항상 진입·진출 엣지 ID를 지정할 수 있다.\n",
- "match7 = match6.copy()\n",
- "match7 = match7[['inter_no', 'move_no', 'inc_dir', 'out_dir', 'inc_edge', 'out_edge', 'node_id']]\n",
- "\n",
- "parent_ids = sorted(inter_node[inter_node.inter_type=='parent'].node_id.unique())\n",
- "child_ids = sorted(inter_node[inter_node.inter_type=='child'].node_id.unique())\n",
- "\n",
- "# (1) 가능한 (진입방향, 진출방향) 목록\n",
- "flows = nema.dropna().apply(lambda row: (row['inc_dir'], row['out_dir']), axis=1).tolist()\n",
- "# (2) 각 교차로별 방향 목록 : pdires (possible directions)\n",
- "pdires = {}\n",
- "for node_id in parent_ids:\n",
- " dires = match7[match7.node_id == node_id][['inc_dir','out_dir']].values.flatten()\n",
- " dires = {dire for dire in dires if type(dire)==str}\n",
- " pdires[node_id] = dires\n",
- "# (3) 각 (교차로, 진입방향) 별 진입id 목록 : inc2id (incoming direction to incoming edge_id)\n",
- "inc2id = {}\n",
- "for node_id in parent_ids:\n",
- " for inc_dir in pdires[node_id]:\n",
- " df = match7[(match7.node_id==node_id) & (match7.inc_dir==inc_dir)]\n",
- " inc2id[(node_id, inc_dir)] = df.inc_edge.iloc[0]\n",
- "# (4) 각 (교차로, 진출방향) 별 진출id 목록 : out2id (outgoing direction to outgoing edge_id)\n",
- "out2id = {}\n",
- "for node_id in parent_ids:\n",
- " for out_dir in pdires[node_id]:\n",
- " df = match7[(match7.node_id==node_id) & (match7.out_dir==out_dir)]\n",
- " out2id[(node_id, out_dir)] = df.out_edge.iloc[0]\n",
- "# (5) 각 교차로별 가능한 (진입방향, 진출방향) 목록 : pflow (possible flows)\n",
- "pflow = {}\n",
- "for node_id in parent_ids:\n",
- " pflow[node_id] = [flow for flow in flows if set(flow).issubset(pdires[node_id])]\n",
- "# (6) 가능한 이동류에 대하여 진입id, 진출id 배정 : matching\n",
- "node2inter = dict(zip(match7['node_id'], match7['inter_no']))\n",
- "dires_right = ['북', '서', '남', '동', '북'] # ex (북, 서), (서, 남) 등은 우회전 flow\n",
- "matching = []\n",
- "for node_id in parent_ids:\n",
- " inter_no = node2inter[node_id]\n",
- " # 좌회전과 직진(1 ~ 16)\n",
- " for (inc_dir, out_dir) in pflow[node_id]:\n",
- " move_no = nema[(nema.inc_dir==inc_dir) & (nema.out_dir==out_dir)].move_no.iloc[0]\n",
- " inc_edge = inc2id[(node_id, inc_dir)]\n",
- " out_edge = out2id[(node_id, out_dir)]\n",
- " new_row = pd.DataFrame({'inter_no':[inter_no], 'move_no':[move_no],\n",
- " 'inc_dir':[inc_dir], 'out_dir':[out_dir],\n",
- " 'inc_edge':[inc_edge], 'out_edge':[out_edge], 'node_id':[node_id]})\n",
- " matching.append(new_row)\n",
- " # 보행신호(17), 전적색(18)\n",
- " new_row = pd.DataFrame({'inter_no':[inter_no] * 2, 'move_no':[17, 18],\n",
- " 'inc_dir':[None]*2, 'out_dir':[None]*2,\n",
- " 'inc_edge':[None]*2, 'out_edge':[None]*2, 'node_id':[node_id]*2})\n",
- " matching.append(new_row)\n",
- " # 신호우회전(21)\n",
- " for d in range(len(dires_right)-1):\n",
- " inc_dir = dires_right[d]\n",
- " out_dir = dires_right[d+1]\n",
- " if {inc_dir, out_dir}.issubset(pdires[node_id]):\n",
- " inc_edge = inc2id[(node_id, inc_dir)]\n",
- " out_edge = out2id[(node_id, out_dir)]\n",
- " new_row = pd.DataFrame({'inter_no':[inter_no], 'move_no':[21],\n",
- " 'inc_dir':[inc_dir], 'out_dir':[out_dir],\n",
- " 'inc_edge':[inc_edge], 'out_edge':[out_edge], 'node_id':[node_id]})\n",
- " matching.append(new_row)\n",
- "matching.append(match7[match7.node_id.isin(child_ids)])\n",
- "matching = pd.concat(matching)\n",
- "matching = matching.dropna().sort_values(by=['inter_no', 'node_id', 'move_no']).reset_index(drop=True)\n",
- "matching['move_no'] = matching['move_no'].astype(int)\n",
- "matching.to_csv('../../Data/tables/matching/matching.csv')\n",
- "display(matching)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# B. 5초 간격으로 이동류번호 수집"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- " 0%| | 0/17280 [00:00, ?it/s]"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "100%|██████████| 17280/17280 [02:07<00:00, 135.82it/s]\n"
- ]
- }
- ],
- "source": [
- "# 5초 단위로 이동류번호 저장 및 신호이력에서 유닉스시각 가져와서 표시, 한시간동안의 데이터만 보관\n",
- "midnight = int(datetime(2024, 1, 5, 0, 0, 0).timestamp())\n",
- "next_day = int(datetime(2024, 1, 6, 0, 0, 0).timestamp())\n",
- "fsecs = range(midnight, next_day, 5) # fsecs : unix time by Five SECondS\n",
- "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
- "# time2move = dict(zip(fsecs,moves)) # move : 어느 순간의 이동류정보\n",
- "history = pd.read_csv('../../Data/tables/history.csv', index_col=0)\n",
- "\n",
- "time2movement = {} # movement : 어느 순간의, 그 순간으로부터 한시간 동안의 (교차로번호 + 현시별이동류번호 + 시작시간)\n",
- "# - 아래 절차를 5초마다 반복\n",
- "for fsec in tqdm(fsecs): # fsec : unix time by Five SECond\n",
- " # 1. 상태 테이블 조회해서 전체 데이터중 필요데이터(교차로번호, A링 현시번호, A링 이동류번호, B링 현시번호, B링 이동류번호)만 수집 : A\n",
- " # move = time2move[fsec]\n",
- " move = pd.read_csv(f'../../Data/tables/moves/move_{fsec}.csv', index_col=0)\n",
- " # 2. 이력 테이블 조회해서 교차로별로 유닉스시간 최대인 데이터(교차로변호, 종료유닉스타임)만 수집 : B\n",
- " recent_histories = [group.iloc[-1:] for _, group in history[history['end_unix'] < fsec].groupby('inter_no')] # 교차로별로 유닉스시간이 최대인 행들\n",
- " if not recent_histories:\n",
- " rhistory = pd.DataFrame({'inter_no':[], 'end_unix':[]}) # recent history\n",
- " else:\n",
- " rhistory = pd.concat(recent_histories)\n",
- " recent_unix = rhistory[['inter_no', 'end_unix']]\n",
- " # 3. 상태 테이블 조회정보(A)와 이력 테이블 조회정보(B) 조인(키값 : 교차로번호) : C\n",
- " move = pd.merge(move, recent_unix, how='left', on='inter_no')\n",
- " move['end_unix'] = move['end_unix'].fillna(0).astype(int)\n",
- " move = move.drop_duplicates()\n",
- " # 4. C데이터 프레임에 신규 컬럼(시작 유닉스타임) 생성 후 종료유닉스 타임 값 입력, 종료 유닉스 타임 컬럼 제거\n",
- " move = move.rename(columns = {'end_unix':'start_unix'})\n",
- " # 5. 이동류 이력정보 READ\n",
- " # - CSV 파일로 서버에 저장된 이동류정보를 읽어옴(파일이 없는 경우에는 데이터가 없는 프레임 D 생성)\n",
- " try:\n",
- " if isinstance(movement, pd.DataFrame): # movement가 존재할 경우 그걸 그대로 씀.\n",
- " pass\n",
- " else: \n",
- " movement = pd.DataFrame()\n",
- " except NameError: # movement가 존재하지 않는 경우 생성\n",
- " movement = pd.DataFrame()\n",
- " # 6. 이동류 이력정보 데이터테이블(D)에 C데이터 add\n",
- " movement = pd.concat([movement, move])\n",
- " # 7. D데이터 프레임에서 중복데이터 제거(교차로번호, 시작 유닉스타임, A링 현시번호, B링 현시번호 같은 행은 제거)\n",
- " movement = movement.drop_duplicates(['inter_no','phas_A','phas_B','start_unix'])\n",
- " # 8. D데이터 보관 시간 기준시간을 시작 유닉스 타임의 최대값 - 3600을 값으로 산출하고, 보관 시간 기준시간보다 작은 시작 유닉스 타임을 가진 행은 모두 제거(1시간 데이터만 보관)\n",
- " movement = movement[movement.start_unix > fsec - 3600]\n",
- " movement = movement.sort_values(by=['start_unix','inter_no','phas_A','phas_B']).reset_index(drop=True)\n",
- "\n",
- " time2movement[fsec] = movement\n",
- " movement.to_csv(f'../../Data/tables/movements/movements_{fsec}.csv')\n",
- "\n",
- "# 각 movement들의 길이 시각화\n",
- "import matplotlib.pyplot as plt\n",
- "plt.plot(fsecs, [len(time2movement[fsec]) for fsec in fsecs])\n",
- "plt.close()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# C. 5분 간격으로 신호이력 수집 및 통합테이블 생성"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [],
- "source": [
- "plan = pd.read_csv('../../Data/tables/plan.csv', index_col=0)\n",
- "history = pd.read_csv('../../Data/tables/history.csv', index_col=0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " start_hour | \n",
- " start_minute | \n",
- " start_seconds | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 1704380400 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 7 | \n",
- " 0 | \n",
- " 1704405600 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 9 | \n",
- " 0 | \n",
- " 1704412800 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 18 | \n",
- " 30 | \n",
- " 1704447000 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " start_hour start_minute start_seconds\n",
- "0 0 0 1704380400\n",
- "1 7 0 1704405600\n",
- "2 9 0 1704412800\n",
- "3 18 30 1704447000"
- ]
- },
- "execution_count": 12,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# split, isplit : A,B 분리 혹은 통합시 사용될 수 있는 딕셔너리\n",
- "splits = {} # splits maps (inter_no, start_hour, start_minute) to split\n",
- "for i, row in plan.iterrows():\n",
- " inter_no = row.inter_no\n",
- " start_hour = row.start_hour\n",
- " start_minute = row.start_minute\n",
- " cycle = row.cycle\n",
- " cums_A = row[[f'dura_A{j}' for j in range(1,9)]].cumsum()\n",
- " cums_B = row[[f'dura_B{j}' for j in range(1,9)]].cumsum()\n",
- " splits[(inter_no, start_hour, start_minute)] = {} # split maps (phas_A, phas_B) to k\n",
- " k = 0\n",
- " for t in range(cycle):\n",
- " new_phas_A = len(cums_A[cums_A < t]) + 1\n",
- " new_phas_B = len(cums_B[cums_B < t]) + 1\n",
- " if k == 0 or ((new_phas_A, new_phas_B) != (phas_A, phas_B)):\n",
- " k += 1\n",
- " phas_A = new_phas_A\n",
- " phas_B = new_phas_B\n",
- " splits[(inter_no, start_hour, start_minute)][(phas_A, phas_B)] = k\n",
- "\n",
- "isplits = {} # the inverse of splits\n",
- "for i in splits:\n",
- " isplits[i] = {splits[i][k]:k for k in splits[i]} # isplit maps k to (phas_A, phas_B)\n",
- "\n",
- "# timetable\n",
- "timetable = plan[['start_hour', 'start_minute']].drop_duplicates()\n",
- "timetable['start_seconds'] = midnight + timetable['start_hour'] * 3600 + timetable['start_minute'] * 60\n",
- "timetable"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "2024-01-05 03:20:00\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " start_unix | \n",
- " dura_A1 | \n",
- " dura_A2 | \n",
- " dura_A3 | \n",
- " dura_A4 | \n",
- " dura_A5 | \n",
- " dura_A6 | \n",
- " dura_A7 | \n",
- " dura_A8 | \n",
- " dura_B1 | \n",
- " dura_B2 | \n",
- " dura_B3 | \n",
- " dura_B4 | \n",
- " dura_B5 | \n",
- " dura_B6 | \n",
- " dura_B7 | \n",
- " dura_B8 | \n",
- " cycle | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 60 | \n",
- " 178 | \n",
- " 1704388800 | \n",
- " 38 | \n",
- " 39 | \n",
- " 40 | \n",
- " 23 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 38 | \n",
- " 39 | \n",
- " 40 | \n",
- " 23 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 140 | \n",
- "
\n",
- " \n",
- " 60 | \n",
- " 201 | \n",
- " 1704388800 | \n",
- " 24 | \n",
- " 24 | \n",
- " 17 | \n",
- " 58 | \n",
- " 17 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 24 | \n",
- " 24 | \n",
- " 17 | \n",
- " 58 | \n",
- " 17 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 140 | \n",
- "
\n",
- " \n",
- " 60 | \n",
- " 202 | \n",
- " 1704388800 | \n",
- " 39 | \n",
- " 101 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 39 | \n",
- " 101 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 140 | \n",
- "
\n",
- " \n",
- " 70 | \n",
- " 206 | \n",
- " 1704388800 | \n",
- " 33 | \n",
- " 35 | \n",
- " 26 | \n",
- " 26 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 33 | \n",
- " 35 | \n",
- " 26 | \n",
- " 26 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 120 | \n",
- "
\n",
- " \n",
- " 56 | \n",
- " 177 | \n",
- " 1704388801 | \n",
- " 36 | \n",
- " 20 | \n",
- " 68 | \n",
- " 26 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 36 | \n",
- " 20 | \n",
- " 68 | \n",
- " 26 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 150 | \n",
- "
\n",
- " \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- "
\n",
- " \n",
- " 78 | \n",
- " 210 | \n",
- " 1704392159 | \n",
- " 43 | \n",
- " 29 | \n",
- " 56 | \n",
- " 22 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 24 | \n",
- " 48 | \n",
- " 56 | \n",
- " 22 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 150 | \n",
- "
\n",
- " \n",
- " 84 | \n",
- " 178 | \n",
- " 1704392160 | \n",
- " 38 | \n",
- " 39 | \n",
- " 40 | \n",
- " 23 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 38 | \n",
- " 39 | \n",
- " 40 | \n",
- " 23 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 140 | \n",
- "
\n",
- " \n",
- " 84 | \n",
- " 201 | \n",
- " 1704392160 | \n",
- " 24 | \n",
- " 24 | \n",
- " 17 | \n",
- " 58 | \n",
- " 17 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 24 | \n",
- " 24 | \n",
- " 17 | \n",
- " 58 | \n",
- " 17 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 140 | \n",
- "
\n",
- " \n",
- " 98 | \n",
- " 206 | \n",
- " 1704392160 | \n",
- " 33 | \n",
- " 35 | \n",
- " 26 | \n",
- " 26 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 33 | \n",
- " 35 | \n",
- " 26 | \n",
- " 26 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 120 | \n",
- "
\n",
- " \n",
- " 84 | \n",
- " 202 | \n",
- " 1704392211 | \n",
- " 39 | \n",
- " 101 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 39 | \n",
- " 101 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 140 | \n",
- "
\n",
- " \n",
- "
\n",
- "
194 rows × 19 columns
\n",
- "
"
- ],
- "text/plain": [
- " inter_no start_unix dura_A1 dura_A2 dura_A3 dura_A4 dura_A5 \\\n",
- "60 178 1704388800 38 39 40 23 0 \n",
- "60 201 1704388800 24 24 17 58 17 \n",
- "60 202 1704388800 39 101 0 0 0 \n",
- "70 206 1704388800 33 35 26 26 0 \n",
- "56 177 1704388801 36 20 68 26 0 \n",
- ".. ... ... ... ... ... ... ... \n",
- "78 210 1704392159 43 29 56 22 0 \n",
- "84 178 1704392160 38 39 40 23 0 \n",
- "84 201 1704392160 24 24 17 58 17 \n",
- "98 206 1704392160 33 35 26 26 0 \n",
- "84 202 1704392211 39 101 0 0 0 \n",
- "\n",
- " dura_A6 dura_A7 dura_A8 dura_B1 dura_B2 dura_B3 dura_B4 dura_B5 \\\n",
- "60 0 0 0 38 39 40 23 0 \n",
- "60 0 0 0 24 24 17 58 17 \n",
- "60 0 0 0 39 101 0 0 0 \n",
- "70 0 0 0 33 35 26 26 0 \n",
- "56 0 0 0 36 20 68 26 0 \n",
- ".. ... ... ... ... ... ... ... ... \n",
- "78 0 0 0 24 48 56 22 0 \n",
- "84 0 0 0 38 39 40 23 0 \n",
- "84 0 0 0 24 24 17 58 17 \n",
- "98 0 0 0 33 35 26 26 0 \n",
- "84 0 0 0 39 101 0 0 0 \n",
- "\n",
- " dura_B6 dura_B7 dura_B8 cycle \n",
- "60 0 0 0 140 \n",
- "60 0 0 0 140 \n",
- "60 0 0 0 140 \n",
- "70 0 0 0 120 \n",
- "56 0 0 0 150 \n",
- ".. ... ... ... ... \n",
- "78 0 0 0 150 \n",
- "84 0 0 0 140 \n",
- "84 0 0 0 140 \n",
- "98 0 0 0 120 \n",
- "84 0 0 0 140 \n",
- "\n",
- "[194 rows x 19 columns]"
- ]
- },
- "execution_count": 13,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "m = 40\n",
- "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
- "present_time = fmins[m] # 현재시점\n",
- "print(datetime.fromtimestamp(present_time))\n",
- "\n",
- "# 1. 조회시점의 유닉스 타임 이전의 신호이력 수집\n",
- "rhistory = history.copy() # recent history\n",
- "rhistory = rhistory[(rhistory.end_unix < present_time)]\n",
- "# 2. 시작 유닉스 타임컬럼 생성 후 종류 유닉스 타임에서 현시별 현시기간 컬럼의 합을 뺀 값으로 입력\n",
- "# - 현시시간의 합을 뺀 시간의 +- 10초 이내에 이전 주기정보가 존재하면 그 유닉스 시간을 시작 유닉스시간 값으로 하고, 존재하지 않으면 현시시간의 합을 뺀 유닉스 시간을 시작 유닉스 시간으로 지정\n",
- "for i, row in rhistory.iterrows():\n",
- " inter_no = row.inter_no\n",
- " end_unix = row.end_unix\n",
- " elapsed_time = row[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]].sum() // 2 # 현시시간 합\n",
- " # 이전 유닉스 존재하지 않음 : 현시시간 합의 차\n",
- " start_unix = end_unix - elapsed_time\n",
- " pre_rows = history[:i] # previous rows\n",
- " if inter_no in pre_rows.inter_no.unique(): # 이전 유닉스 존재\n",
- " pre_unix = pre_rows[pre_rows.inter_no == inter_no]['end_unix'].iloc[-1] # previous unix time\n",
- " # 이전 유닉스 존재, abs < 10 : 이전 유닉스\n",
- " if abs(pre_unix - start_unix) < 10:\n",
- " start_unix = pre_unix\n",
- " # 이전 유닉스 존재, abs >=10 : 현시시간 합의 차\n",
- " else:\n",
- " pass\n",
- " rhistory.loc[i, 'start_unix'] = start_unix \n",
- "rhistory[rhistory.isna()] = 0\n",
- "rhistory['start_unix'] = rhistory['start_unix'].astype(int)\n",
- "rhistory[['inter_no', 'start_unix', 'cycle']][rhistory.inter_no==175]\n",
- "rhistory = rhistory[['inter_no', 'start_unix'] + [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)] + ['cycle']]\n",
- "rhistory\n",
- "\n",
- "# 2-1. 참값 판단 프로세스\n",
- "hours = np.array(range(midnight, next_day + 1, 3600)) # 정각에 해당하는 시각들 목록\n",
- "\n",
- "def calculate_DS(rhist, curr_unix):\n",
- " ghour_lt_curr_unix = hours[hours <= curr_unix].max() # the greatest hour less than (or equal to) curr_unix\n",
- " start_unixes = rhist.start_unix.unique()\n",
- " start_unixes_lt_ghour = np.sort(start_unixes[start_unixes < ghour_lt_curr_unix]) # start unixes less than ghour_lt_curr_unix\n",
- " # 기준유닉스(base_unix) : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 start_unix\n",
- " if list(start_unixes_lt_ghour):\n",
- " base_unix = start_unixes_lt_ghour[-5]\n",
- " # start_unixes_lt_ghour가 비었을 경우에는 맨 앞 start_unix로 base_unix를 지정\n",
- " else:\n",
- " base_unix = rhist.start_unix.min()\n",
- " D_n = curr_unix - base_unix\n",
- " S_n_durs = rhist[(rhist.start_unix > base_unix) & (rhist.start_unix <= curr_unix)] \\\n",
- " [[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
- " S_n = S_n_durs.values.sum() // 2\n",
- " return D_n, S_n\n",
- "\n",
- "rhists = []\n",
- "for inter_no in sorted(rhistory.inter_no.unique()):\n",
- " rhist = rhistory.copy()[rhistory.inter_no==inter_no]\n",
- " rhist = rhist.drop_duplicates(subset=['start_unix']).reset_index(drop=True)\n",
- "\n",
- " # D_n 및 S_n 값 정의\n",
- " rhist['D_n'] = 0 # D_n : 시간차이\n",
- " rhist['S_n'] = 0 # S_n : 현시시간합\n",
- " for n in range(len(rhist)):\n",
- " curr_unix = rhist.iloc[n].start_unix # current start_unix\n",
- " rhist.loc[n, ['D_n', 'S_n']] = calculate_DS(rhist, curr_unix)\n",
- "\n",
- " # 이전시각, 현재시각\n",
- " prev_unix = rhist.loc[0, 'start_unix'] # previous start_unix\n",
- " curr_unix = rhist.loc[1, 'start_unix'] # current start_unix\n",
- "\n",
- " # rhist의 마지막 행에 도달할 때까지 반복\n",
- " while True:\n",
- " n = rhist[rhist.start_unix==curr_unix].index[0]\n",
- " cycle = rhist.loc[n, 'cycle']\n",
- " D_n = rhist.loc[n, 'D_n']\n",
- " S_n = rhist.loc[n, 'S_n']\n",
- " # 참값인 경우\n",
- " if (abs(D_n - S_n) <= 5):\n",
- " pass\n",
- " # 참값이 아닌 경우\n",
- " else:\n",
- " # 2-1-1. 결측치 처리 : 인접한 두 start_unix의 차이가 계획된 주기의 두 배보다 크면 결측이 일어났다고 판단, 신호계획의 현시시간으로 \"대체\"\n",
- " if curr_unix - prev_unix >= 2 * cycle:\n",
- " # prev_unix를 계획된 주기만큼 늘려가면서 한 행씩 채워나간다.\n",
- " # (curr_unix와의 차이가 계획된 주기보다 작거나 같아질 때까지)\n",
- " new_rows = []\n",
- " while curr_unix - prev_unix > cycle:\n",
- " prev_unix += cycle\n",
- " # 신호 계획(prow) 불러오기\n",
- " start_seconds = np.array(timetable.start_seconds)\n",
- " idx = (start_seconds <= prev_unix).sum() - 1\n",
- " start_hour = timetable.iloc[idx].start_hour\n",
- " start_minute = timetable.iloc[idx].start_minute\n",
- " prow = plan.copy()[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
- " # prow에서 필요한 부분을 rhist에 추가\n",
- " prow['start_unix'] = prev_unix\n",
- " prow = prow.drop(['start_hour', 'start_minute', 'offset'], axis=1)\n",
- " cycle = prow.iloc[0].cycle\n",
- " rhist = pd.concat([rhist, prow])\n",
- " rhist = rhist.sort_values(by='start_unix').reset_index(drop=True)\n",
- " n += 1\n",
- "\n",
- " # 2-1-2. 이상치 처리 : 비율에 따라 해당 행을 \"삭제\"(R_n <= 0.5) 또는 \"조정\"(R_n > 0.5)한다\n",
- " R_n = (curr_unix - prev_unix) / cycle # R_n : 비율\n",
- " # R_n이 0.5보다 작거나 같으면 해당 행을 삭제\n",
- " if R_n <= 0.5:\n",
- " rhist = rhist.drop(index=n).reset_index(drop=True)\n",
- " # 행삭제에 따른 curr_unix, R_n 재정의\n",
- " curr_unix = rhist.loc[n, 'start_unix']\n",
- " R_n = (curr_unix - prev_unix) / cycle # R_n : 비율\n",
- "\n",
- " # R_n이 0.5보다 크면 해당 행 조정 (비율을 유지한 채로 현시시간 대체)\n",
- " if R_n > 0.5:\n",
- " # 신호 계획(prow) 불러오기\n",
- " start_seconds = np.array(timetable.start_seconds)\n",
- " idx = (start_seconds <= curr_unix).sum() - 1\n",
- " start_hour = timetable.iloc[idx].start_hour\n",
- " start_minute = timetable.iloc[idx].start_minute\n",
- " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
- " # 조정된 현시시간 (prow에 R_n을 곱하고 정수로 바꿈)\n",
- " adjusted_dur = prow.copy()[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] * R_n\n",
- " int_parts = adjusted_dur.iloc[0].apply(lambda x: int(x))\n",
- " frac_parts = adjusted_dur.iloc[0] - int_parts\n",
- " difference = round(adjusted_dur.iloc[0].sum()) - int_parts.sum()\n",
- " for _ in range(difference): # 소수 부분이 가장 큰 상위 'difference'개의 값에 대해 올림 처리\n",
- " max_frac_index = frac_parts.idxmax()\n",
- " int_parts[max_frac_index] += 1\n",
- " frac_parts[max_frac_index] = 0 # 이미 처리된 항목은 0으로 설정\n",
- " # rhist에 조정된 현시시간을 반영\n",
- " rhist.loc[n, [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] = int_parts.values\n",
- " rhist.loc[n, 'cycle'] = int_parts.sum().sum() // 2\n",
- "\n",
- " if n == rhist.index[-1]:\n",
- " break\n",
- " prev_unix = curr_unix\n",
- " curr_unix = rhist.loc[n+1, 'start_unix']\n",
- " # rhist['start_dt'] = rhist['start_unix'].map(lambda x:datetime.fromtimestamp(x))\n",
- "\n",
- " # 생략해도 무방할 코드\n",
- " rhist = rhist.reset_index(drop=True)\n",
- " rhist = rhist.sort_values(by=['start_unix'])\n",
- "\n",
- " # D_n 및 S_n 값 재정의\n",
- " for n in range(len(rhist)):\n",
- " curr_unix = rhist.iloc[n].start_unix # current start_unix\n",
- " rhist.loc[n, ['D_n', 'S_n']] = calculate_DS(rhist, curr_unix)\n",
- " rhists.append(rhist)\n",
- "rhists = pd.concat(rhists).sort_values(by=['start_unix','inter_no'])\n",
- "rhists = rhists[rhists.start_unix >= present_time - 3600]\n",
- "rhists = rhists.drop(columns=['D_n', 'S_n'])\n",
- "rhists"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 34,
- "metadata": {},
- "outputs": [
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- " 0%| | 0/17280 [00:00, ?it/s]"
- ]
- },
- {
- "name": "stderr",
- "output_type": "stream",
- "text": [
- "100%|██████████| 17280/17280 [00:18<00:00, 929.46it/s] \n"
- ]
- }
- ],
- "source": [
- "file_path = '../../Data/tables/movements/'\n",
- "movements = [pd.read_csv(file_path + file, index_col=0) for file in tqdm(os.listdir(file_path))]\n",
- "movements = pd.concat(movements).drop_duplicates()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phas_A | \n",
- " phas_B | \n",
- " move_A | \n",
- " move_B | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 8 | \n",
- " 175 | \n",
- " 1 | \n",
- " 1 | \n",
- " 8 | \n",
- " 4 | \n",
- "
\n",
- " \n",
- " 15 | \n",
- " 175 | \n",
- " 2 | \n",
- " 2 | \n",
- " 7 | \n",
- " 3 | \n",
- "
\n",
- " \n",
- " 20 | \n",
- " 175 | \n",
- " 3 | \n",
- " 3 | \n",
- " 6 | \n",
- " 1 | \n",
- "
\n",
- " \n",
- " 24 | \n",
- " 175 | \n",
- " 3 | \n",
- " 4 | \n",
- " 6 | \n",
- " 2 | \n",
- "
\n",
- " \n",
- " 26 | \n",
- " 175 | \n",
- " 4 | \n",
- " 4 | \n",
- " 5 | \n",
- " 2 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phas_A phas_B move_A move_B\n",
- "8 175 1 1 8 4\n",
- "15 175 2 2 7 3\n",
- "20 175 3 3 6 1\n",
- "24 175 3 4 6 2\n",
- "26 175 4 4 5 2"
- ]
- },
- "execution_count": 20,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "movements_wo_start_unix_list = [] # movements without start_unix\n",
- "for inter_no in sorted(movements.inter_no.unique()):\n",
- " movements_wo_start_unix = movements[movements_wo_start_unix.inter_no==inter_no]\n",
- " movements_wo_start_unix = movements_wo_start_unix[['inter_no', 'phas_A', 'phas_B', 'move_A', 'move_B']]\n",
- " movements_wo_start_unix = movements_wo_start_unix.drop_duplicates().sort_values(by=['phas_A','phas_B'])\n",
- " movements_wo_start_unix_list.append(movements_wo_start_unix)\n",
- "movements_wo_start_unix = pd.concat(movements_wo_start_unix_list)\n",
- "movements_wo_start_unix.head()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 67,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " start_unix | \n",
- " phas_A | \n",
- " phas_B | \n",
- " duration | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 178 | \n",
- " 1704388800 | \n",
- " 1 | \n",
- " 1 | \n",
- " 38 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 178 | \n",
- " 1704388800 | \n",
- " 2 | \n",
- " 2 | \n",
- " 39 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 178 | \n",
- " 1704388800 | \n",
- " 3 | \n",
- " 3 | \n",
- " 40 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 178 | \n",
- " 1704388800 | \n",
- " 4 | \n",
- " 4 | \n",
- " 23 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 201 | \n",
- " 1704388800 | \n",
- " 1 | \n",
- " 1 | \n",
- " 24 | \n",
- "
\n",
- " \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- "
\n",
- " \n",
- " 767 | \n",
- " 206 | \n",
- " 1704392160 | \n",
- " 2 | \n",
- " 2 | \n",
- " 35 | \n",
- "
\n",
- " \n",
- " 768 | \n",
- " 206 | \n",
- " 1704392160 | \n",
- " 3 | \n",
- " 3 | \n",
- " 26 | \n",
- "
\n",
- " \n",
- " 769 | \n",
- " 206 | \n",
- " 1704392160 | \n",
- " 4 | \n",
- " 4 | \n",
- " 26 | \n",
- "
\n",
- " \n",
- " 770 | \n",
- " 202 | \n",
- " 1704392211 | \n",
- " 1 | \n",
- " 1 | \n",
- " 39 | \n",
- "
\n",
- " \n",
- " 771 | \n",
- " 202 | \n",
- " 1704392211 | \n",
- " 2 | \n",
- " 2 | \n",
- " 101 | \n",
- "
\n",
- " \n",
- "
\n",
- "
772 rows × 5 columns
\n",
- "
"
- ],
- "text/plain": [
- " inter_no start_unix phas_A phas_B duration\n",
- "0 178 1704388800 1 1 38\n",
- "1 178 1704388800 2 2 39\n",
- "2 178 1704388800 3 3 40\n",
- "3 178 1704388800 4 4 23\n",
- "4 201 1704388800 1 1 24\n",
- ".. ... ... ... ... ...\n",
- "767 206 1704392160 2 2 35\n",
- "768 206 1704392160 3 3 26\n",
- "769 206 1704392160 4 4 26\n",
- "770 202 1704392211 1 1 39\n",
- "771 202 1704392211 2 2 101\n",
- "\n",
- "[772 rows x 5 columns]"
- ]
- },
- "execution_count": 67,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 계층화된 형태로 변환\n",
- "hrhists = [] # hierarchied recent history\n",
- "for i, row in rhists.iterrows():\n",
- " inter_no = row.inter_no\n",
- " start_unix = row.start_unix\n",
- "\n",
- " ind = (timetable['start_seconds'] <= row.start_unix).sum() - 1\n",
- " start_hour = timetable.iloc[ind].start_hour\n",
- " start_minute = timetable.iloc[ind].start_minute\n",
- " isplit = isplits[(inter_no, start_hour, start_minute)]\n",
- " phas_As = [isplit[j][0] for j in isplit.keys()]\n",
- " phas_Bs = [isplit[j][1] for j in isplit.keys()]\n",
- " durs_A = row[[f'dura_A{j}' for j in range(1,9)]]\n",
- " durs_B = row[[f'dura_B{j}' for j in range(1,9)]]\n",
- " durations = []\n",
- " for j in range(1, len(isplit)+1):\n",
- " ja = isplit[j][0]\n",
- " jb = isplit[j][1]\n",
- " if ja == jb:\n",
- " durations.append(min(durs_A[ja-1], durs_B[jb-1]))\n",
- " else:\n",
- " durations.append(abs(durs_A[ja-1] - durs_B[ja-1]))\n",
- " new_rows = pd.DataFrame({'inter_no':[inter_no] * len(durations), 'start_unix':[start_unix] * len(durations),\n",
- " 'phas_A':phas_As, 'phas_B':phas_Bs, 'duration':durations})\n",
- " hrhists.append(new_rows)\n",
- "hrhists = pd.concat(hrhists)\n",
- "hrhists = hrhists.sort_values(by = ['start_unix', 'inter_no', 'phas_A', 'phas_B']).reset_index(drop=True)\n",
- "hrhists"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 133,
- "metadata": {},
- "outputs": [],
- "source": [
- "movement = time2movement[present_time]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 138,
- "metadata": {},
- "outputs": [],
- "source": [
- "# 중복을 제거하고 (inter_no, start_unix) 쌍을 만듭니다.\n",
- "hrhists_inter_unix = set(hrhists[['inter_no', 'start_unix']].drop_duplicates().itertuples(index=False, name=None))\n",
- "movement_inter_unix = set(movement[['inter_no', 'start_unix']].drop_duplicates().itertuples(index=False, name=None))\n",
- "\n",
- "# hrhists에는 있지만 movement에는 없는 (inter_no, start_unix) 쌍을 찾습니다.\n",
- "missing_in_movement = hrhists_inter_unix - movement_inter_unix\n",
- "\n",
- "# 새로운 행들을 생성합니다.\n",
- "new_rows = []\n",
- "for inter_no, start_unix in missing_in_movement:\n",
- " # movements_wo_start_unix에서 해당 inter_no의 데이터를 찾습니다.\n",
- " new_row = movements_wo_start_unix[movements_wo_start_unix['inter_no'] == inter_no].copy()\n",
- " # start_unix 값을 설정합니다.\n",
- " new_row['start_unix'] = start_unix\n",
- " new_rows.append(new_row)\n",
- "\n",
- "# 새로운 데이터프레임을 생성하고 기존 movement 데이터프레임과 합칩니다.\n",
- "new_movement = pd.concat(new_rows, ignore_index=True)\n",
- "movement_updated = pd.concat([movement, new_movement], ignore_index=True)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 143,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " node_id | \n",
- " start_unix | \n",
- " phas_A | \n",
- " phas_B | \n",
- " duration | \n",
- " inc_edge_A | \n",
- " out_edge_A | \n",
- " inc_edge_B | \n",
- " out_edge_B | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 177 | \n",
- " i2 | \n",
- " 1704388801 | \n",
- " 1 | \n",
- " 1 | \n",
- " 36 | \n",
- " -571542809_01 | \n",
- " 571542811_01 | \n",
- " 571542811_02 | \n",
- " 571542809_01 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 177 | \n",
- " i2 | \n",
- " 1704388801 | \n",
- " 2 | \n",
- " 2 | \n",
- " 20 | \n",
- " 571542811_02 | \n",
- " 571542107_01 | \n",
- " -571542809_01 | \n",
- " 571542809_01 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 177 | \n",
- " i2 | \n",
- " 1704388801 | \n",
- " 3 | \n",
- " 3 | \n",
- " 68 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 177 | \n",
- " i2 | \n",
- " 1704388801 | \n",
- " 4 | \n",
- " 4 | \n",
- " 26 | \n",
- " -571542809_01 | \n",
- " 571542811_01 | \n",
- " 571542107_02 | \n",
- " 571542809_01 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 176 | \n",
- " i1 | \n",
- " 1704388850 | \n",
- " 1 | \n",
- " 1 | \n",
- " 37 | \n",
- " -571542810_01 | \n",
- " -571542797_02.99 | \n",
- " 571542797_02.99 | \n",
- " 571542810_01 | \n",
- "
\n",
- " \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- "
\n",
- " \n",
- " 748 | \n",
- " 206 | \n",
- " i7 | \n",
- " 1704392160 | \n",
- " 2 | \n",
- " 2 | \n",
- " 35 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 749 | \n",
- " 206 | \n",
- " i7 | \n",
- " 1704392160 | \n",
- " 3 | \n",
- " 3 | \n",
- " 26 | \n",
- " -571511538_02 | \n",
- " 571542073_02 | \n",
- " 571542073_01 | \n",
- " 571511538_02 | \n",
- "
\n",
- " \n",
- " 750 | \n",
- " 206 | \n",
- " i7 | \n",
- " 1704392160 | \n",
- " 4 | \n",
- " 4 | \n",
- " 26 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 751 | \n",
- " 202 | \n",
- " i9 | \n",
- " 1704392211 | \n",
- " 1 | \n",
- " 1 | \n",
- " 39 | \n",
- " 571510152_02 | \n",
- " -571510152_01 | \n",
- " 571510152_01 | \n",
- " 571510152_01.65 | \n",
- "
\n",
- " \n",
- " 752 | \n",
- " 202 | \n",
- " i9 | \n",
- " 1704392211 | \n",
- " 2 | \n",
- " 2 | \n",
- " 101 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- "
\n",
- "
757 rows × 10 columns
\n",
- "
"
- ],
- "text/plain": [
- " inter_no node_id start_unix phas_A phas_B duration inc_edge_A \\\n",
- "0 177 i2 1704388801 1 1 36 -571542809_01 \n",
- "1 177 i2 1704388801 2 2 20 571542811_02 \n",
- "2 177 i2 1704388801 3 3 68 NaN \n",
- "3 177 i2 1704388801 4 4 26 -571542809_01 \n",
- "4 176 i1 1704388850 1 1 37 -571542810_01 \n",
- ".. ... ... ... ... ... ... ... \n",
- "748 206 i7 1704392160 2 2 35 NaN \n",
- "749 206 i7 1704392160 3 3 26 -571511538_02 \n",
- "750 206 i7 1704392160 4 4 26 NaN \n",
- "751 202 i9 1704392211 1 1 39 571510152_02 \n",
- "752 202 i9 1704392211 2 2 101 NaN \n",
- "\n",
- " out_edge_A inc_edge_B out_edge_B \n",
- "0 571542811_01 571542811_02 571542809_01 \n",
- "1 571542107_01 -571542809_01 571542809_01 \n",
- "2 NaN NaN NaN \n",
- "3 571542811_01 571542107_02 571542809_01 \n",
- "4 -571542797_02.99 571542797_02.99 571542810_01 \n",
- ".. ... ... ... \n",
- "748 NaN NaN NaN \n",
- "749 571542073_02 571542073_01 571511538_02 \n",
- "750 NaN NaN NaN \n",
- "751 -571510152_01 571510152_01 571510152_01.65 \n",
- "752 NaN NaN NaN \n",
- "\n",
- "[757 rows x 10 columns]"
- ]
- },
- "execution_count": 143,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "movedur = pd.merge(movement_updated, hrhists, how='inner', on=['inter_no', 'start_unix', 'phas_A', 'phas_B']) # movements and durations\n",
- "movedur = movedur.sort_values(by=['start_unix', 'inter_no', 'phas_A','phas_B'])\n",
- "movedur = movedur[['inter_no', 'start_unix', 'phas_A', 'phas_B', 'move_A', 'move_B', 'duration']]\n",
- "\n",
- "# 이동류 매칭 테이블에서 진입id, 진출id를 가져와서 붙임.\n",
- "for i, row in movedur.iterrows():\n",
- " inter_no = row.inter_no\n",
- " start_unix = row.start_unix\n",
- " # incoming and outgoing edges A\n",
- " move_A = row.move_A\n",
- " if move_A in [17, 18]:\n",
- " inc_edge_A = np.nan\n",
- " out_edge_A = np.nan\n",
- " else:\n",
- " match_A = matching[(matching.inter_no == inter_no) & (matching.move_no == move_A)].iloc[0]\n",
- " inc_edge_A = match_A.inc_edge\n",
- " out_edge_A = match_A.out_edge\n",
- " movedur.loc[i, ['inc_edge_A', 'out_edge_A']] = [inc_edge_A, out_edge_A]\n",
- " # incoming and outgoing edges B\n",
- " move_B = row.move_B\n",
- " if move_B in [17, 18]:\n",
- " inc_edge_B = np.nan\n",
- " out_edge_B = np.nan\n",
- " else:\n",
- " match_B = matching[(matching.inter_no == inter_no) & (matching.move_no == move_B)].iloc[0]\n",
- " inc_edge_B = match_B.inc_edge\n",
- " out_edge_B = match_B.out_edge\n",
- " movedur.loc[i, ['inc_edge_B', 'out_edge_B']] = [inc_edge_B, out_edge_B]\n",
- "\n",
- "# 이동류 컬럼 제거\n",
- "movedur = movedur.drop(['move_A', 'move_B'], axis=1)\n",
- "\n",
- "histid = movedur.copy() # history with edge ids (incoming and outgoing edge ids)\n",
- "histid['node_id'] = histid['inter_no'].map(inter2node)\n",
- "histid = histid[['inter_no', 'node_id', 'start_unix', 'phas_A', 'phas_B', 'duration', 'inc_edge_A', 'out_edge_A', 'inc_edge_B', 'out_edge_B']]\n",
- "histid = histid[histid.start_unix > present_time - 3600]\n",
- "histid"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 71,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "2024-01-05 16:40:00\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " node_id | \n",
- " start_unix | \n",
- " phas_A | \n",
- " phas_B | \n",
- " duration | \n",
- " inc_edge_A | \n",
- " out_edge_A | \n",
- " inc_edge_B | \n",
- " out_edge_B | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 202 | \n",
- " i9 | \n",
- " 1704436810 | \n",
- " 1 | \n",
- " 1 | \n",
- " 46 | \n",
- " 571510152_02 | \n",
- " -571510152_01 | \n",
- " 571510152_01 | \n",
- " 571510152_01.65 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 202 | \n",
- " i9 | \n",
- " 1704436810 | \n",
- " 2 | \n",
- " 2 | \n",
- " 114 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 178 | \n",
- " i3 | \n",
- " 1704436860 | \n",
- " 1 | \n",
- " 1 | \n",
- " 38 | \n",
- " 571540304_02 | \n",
- " 571556450_01 | \n",
- " 571556450_02 | \n",
- " 571540304_01 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 178 | \n",
- " i3 | \n",
- " 1704436860 | \n",
- " 2 | \n",
- " 2 | \n",
- " 39 | \n",
- " 571556450_02 | \n",
- " 571500475_01 | \n",
- " 571540304_02 | \n",
- " 571540303_01 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 178 | \n",
- " i3 | \n",
- " 1704436860 | \n",
- " 3 | \n",
- " 3 | \n",
- " 43 | \n",
- " 571540303_02.21 | \n",
- " 571556450_01 | \n",
- " 571540303_02.21 | \n",
- " 571500475_01 | \n",
- "
\n",
- " \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- "
\n",
- " \n",
- " 477 | \n",
- " 202 | \n",
- " i9 | \n",
- " 1704440171 | \n",
- " 2 | \n",
- " 2 | \n",
- " 114 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 478 | \n",
- " 206 | \n",
- " i7 | \n",
- " 1704440171 | \n",
- " 1 | \n",
- " 1 | \n",
- " 45 | \n",
- " -571511538_02 | \n",
- " 571542073_02 | \n",
- " 571542073_01 | \n",
- " 571511538_02 | \n",
- "
\n",
- " \n",
- " 479 | \n",
- " 206 | \n",
- " i7 | \n",
- " 1704440171 | \n",
- " 2 | \n",
- " 2 | \n",
- " 53 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 480 | \n",
- " 206 | \n",
- " i7 | \n",
- " 1704440171 | \n",
- " 3 | \n",
- " 3 | \n",
- " 26 | \n",
- " -571511538_02 | \n",
- " 571542073_02 | \n",
- " 571542073_01 | \n",
- " 571511538_02 | \n",
- "
\n",
- " \n",
- " 481 | \n",
- " 206 | \n",
- " i7 | \n",
- " 1704440171 | \n",
- " 4 | \n",
- " 4 | \n",
- " 26 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- "
\n",
- "
482 rows × 10 columns
\n",
- "
"
- ],
- "text/plain": [
- " inter_no node_id start_unix phas_A phas_B duration inc_edge_A \\\n",
- "0 202 i9 1704436810 1 1 46 571510152_02 \n",
- "1 202 i9 1704436810 2 2 114 NaN \n",
- "2 178 i3 1704436860 1 1 38 571540304_02 \n",
- "3 178 i3 1704436860 2 2 39 571556450_02 \n",
- "4 178 i3 1704436860 3 3 43 571540303_02.21 \n",
- ".. ... ... ... ... ... ... ... \n",
- "477 202 i9 1704440171 2 2 114 NaN \n",
- "478 206 i7 1704440171 1 1 45 -571511538_02 \n",
- "479 206 i7 1704440171 2 2 53 NaN \n",
- "480 206 i7 1704440171 3 3 26 -571511538_02 \n",
- "481 206 i7 1704440171 4 4 26 NaN \n",
- "\n",
- " out_edge_A inc_edge_B out_edge_B \n",
- "0 -571510152_01 571510152_01 571510152_01.65 \n",
- "1 NaN NaN NaN \n",
- "2 571556450_01 571556450_02 571540304_01 \n",
- "3 571500475_01 571540304_02 571540303_01 \n",
- "4 571556450_01 571540303_02.21 571500475_01 \n",
- ".. ... ... ... \n",
- "477 NaN NaN NaN \n",
- "478 571542073_02 571542073_01 571511538_02 \n",
- "479 NaN NaN NaN \n",
- "480 571542073_02 571542073_01 571511538_02 \n",
- "481 NaN NaN NaN \n",
- "\n",
- "[482 rows x 10 columns]"
- ]
- },
- "execution_count": 71,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "m = 200\n",
- "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
- "present_time = fmins[m] # 현재시점\n",
- "print(datetime.fromtimestamp(present_time))\n",
- "\n",
- "# (구) make_rhistory\n",
- "Rhists = [] # Recent history (1시간 이내)\n",
- "for inter_no in history.inter_no.unique():\n",
- " # - 5분마다 신호이력 데이터 수집해서 통합테이블 생성할때\n",
- " # 1. 조회시점의 유닉스 타임 이전의 신호이력 수집\n",
- " rhistory = history.copy() # recent history\n",
- " rhistory = rhistory[(rhistory.end_unix < present_time)]\n",
- " hours = np.array(range(midnight, next_day + 1, 3600))\n",
- " rhist = rhistory.copy()[rhistory.inter_no == inter_no] # 특정한 inter_no\n",
- " rhist = rhist.reset_index(drop=True)\n",
- " new_rows = []\n",
- " # 1-1. 결측치 처리 : 인접한 두 end_unix의 차이가 계획된 주기의 두 배보다 크면 결측이 일어났다고 판단\n",
- " for n in range(len(rhist) - 1):\n",
- " curr_unix = rhist.iloc[n].end_unix # current end_unix\n",
- " next_unix = rhist.iloc[n+1].end_unix # next end_unix\n",
- " cycle = rhist.iloc[n].cycle\n",
- " if next_unix - curr_unix >= 2 * cycle:\n",
- " # 현재 unix를 계획된 주기만큼 늘려가면서 한 행씩 채워나간다.\n",
- " #(다음 unix와의 차이가 계획된 주기보다 작거나 같아질 때까지)\n",
- " while next_unix - curr_unix > cycle:\n",
- " curr_unix += cycle\n",
- " start_seconds = np.array(timetable.start_seconds)\n",
- " idx = (start_seconds <= curr_unix).sum() - 1\n",
- " start_hour = timetable.iloc[idx].start_hour\n",
- " start_minute = timetable.iloc[idx].start_minute\n",
- " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
- " prow = prow.drop(['start_hour', 'start_minute'], axis=1)\n",
- " prow['end_unix'] = curr_unix\n",
- " cycle = prow.iloc[0].cycle\n",
- " new_rows.append(prow)\n",
- " rhist = pd.concat([rhist] + new_rows).sort_values(['end_unix'])\n",
- " rhist = rhist.reset_index(drop=True)\n",
- "\n",
- " # 1-2. 이상치 처리 : 기준유닉스로부터의 시간차이와 현시시간합이 11 이상 차이나면 이상치가 발생했다고 판단\n",
- " Rhist = rhist.copy() # recent history 1704393231\n",
- " Rhist = Rhist[(Rhist.end_unix >= present_time - 3600)] # Recent history (1시간 이내)\n",
- " Rhist = Rhist.reset_index(drop=True)\n",
- " Rhist['D_n'] = 0\n",
- " Rhist['S_n'] = 0\n",
- " for n in range(len(Rhist)):\n",
- " curr_unix = Rhist.iloc[n].end_unix # current end_unix\n",
- " cycle = Rhist.iloc[n].cycle\n",
- " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
- " end_unixes = rhist.end_unix.unique()\n",
- " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
- " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
- " # D_n : 시간차이 \n",
- " D_n = curr_unix - base_unix\n",
- " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
- " # S_n : 현시시간합\n",
- " S_n = ddurations.values.sum() // 2\n",
- " Rhist.loc[n, ['D_n', 'S_n']] = [D_n, S_n]\n",
- " n = 1\n",
- " while n < len(Rhist):\n",
- " prev_unix = Rhist[Rhist.index==n-1]['end_unix'].iloc[0] # previous end_unix\n",
- " curr_unix = Rhist[Rhist.index==n]['end_unix'].iloc[0] # current end_unix\n",
- " R_n = (curr_unix - prev_unix) / cycle\n",
- " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
- " end_unixes = rhist.end_unix.unique()\n",
- " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
- " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
- " # D_n : 시간차이\n",
- " D_n = curr_unix - base_unix\n",
- " # S_n : 현시시간합\n",
- " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
- " S_n = ddurations.values.sum() // 2\n",
- " # 비율이 0.5보다 작거나 같으면 해당 행을 삭제\n",
- " if (abs(D_n - S_n) > 10) & (R_n <= 0.5):\n",
- " Rhist = Rhist.drop(index=n)\n",
- " n += 1\n",
- " # 행삭제에 따른 curr_unix, D_n, S_n 등 재정의\n",
- " if not Rhist[Rhist.index==n]['end_unix'].empty: # 마지막 행을 삭제하여 뒤의 행이 없을 때를 대비\n",
- " curr_unix = Rhist[Rhist.index==n]['end_unix'].iloc[0] # current end_unix\n",
- " R_n = (curr_unix - prev_unix) / cycle\n",
- " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
- " end_unixes = rhist.end_unix.unique()\n",
- " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
- " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
- " # D_n : 시간차이\n",
- " D_n = curr_unix - base_unix\n",
- " # S_n : 현시시간합\n",
- " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
- " S_n = ddurations.values.sum() // 2\n",
- " # 비율이 0.5보다 크면 해당 행 조정 (비율을 유지한 채로 현시시간 대체)\n",
- " if (abs(D_n - S_n) > 10) & (R_n > 0.5):\n",
- " start_seconds = np.array(timetable.start_seconds)\n",
- " idx = (start_seconds <= curr_unix).sum() - 1\n",
- " start_hour = timetable.iloc[idx].start_hour\n",
- " start_minute = timetable.iloc[idx].start_minute\n",
- " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)].copy().reset_index(drop=True).iloc[0] # planned row\n",
- " adjusted_dur = prow[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] * R_n\n",
- " # 조정된 현시시간을 정수로 바꿈\n",
- " int_parts = adjusted_dur.apply(lambda x: int(x))\n",
- " frac_parts = adjusted_dur - int_parts\n",
- " difference = int(round(adjusted_dur.sum())) - int_parts.sum()\n",
- " # 소수 부분이 가장 큰 상위 'difference'개의 값에 대해 올림 처리\n",
- " for _ in range(difference):\n",
- " max_frac_index = frac_parts.idxmax()\n",
- " int_parts[max_frac_index] += 1\n",
- " frac_parts[max_frac_index] = 0 # 이미 처리된 항목은 0으로 설정\n",
- " Rhist.loc[n, [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] = int_parts.values\n",
- " Rhist.loc[n, 'cycle'] = int_parts.sum() // 2\n",
- " n += 1\n",
- " Rhist = Rhist.drop(columns=['offset', 'D_n', 'S_n'])\n",
- " Rhists.append(Rhist)\n",
- "Rhists = pd.concat(Rhists)\n",
- "Rhists = Rhists.sort_values(by=['end_unix', 'inter_no']).reset_index(drop=True)\n",
- "\n",
- "# (구) make_histid\n",
- "# 2. 시작 유닉스 타임컬럼 생성 후 종류 유닉스 타임에서 현시별 현시기간 컬럼의 합을 뺀 값으로 입력\n",
- "# - 현시시간의 합을 뺀 시간의 +- 10초 이내에 이전 주기정보가 존재하면 그 유닉스 시간을 시작 유닉스시간 값으로 하고, 존재하지 않으면 현시시간의 합을 뺀 유닉스 시간을 시작 유닉스 시간으로 지정\n",
- "for i, row in rhistory.iterrows():\n",
- " # 이전 유닉스 존재하지 않음 => 현시시간 합의 차\n",
- " # 이전 유닉스 존재, abs < 10 => 이전 유닉스\n",
- " # 이전 유닉스 존재, abs >=10 => 현시시간 합의 차\n",
- " inter_no = row.inter_no\n",
- " end_unix = row.end_unix\n",
- " elapsed_time = row[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]].sum() // 2 # 현시시간 합\n",
- " start_unix = end_unix - elapsed_time\n",
- " pre_rows = history[:i] # previous rows\n",
- " if inter_no in pre_rows.inter_no.unique(): # 이전 유닉스 존재\n",
- " pre_unix = pre_rows[pre_rows.inter_no == inter_no]['end_unix'].iloc[-1] # previous unix time\n",
- " if abs(pre_unix - start_unix) < 10: # abs < 10\n",
- " start_unix = pre_unix\n",
- " else: # abs >= 10\n",
- " pass\n",
- " rhistory.loc[i, 'start_unix'] = start_unix \n",
- "rhistory[rhistory.isna()] = 0\n",
- "rhistory['start_unix'] = rhistory['start_unix'].astype(int)\n",
- "rhistory = rhistory[['inter_no', 'start_unix'] + [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)] + ['cycle']]\n",
- "\n",
- "# 계층화된 형태로 변환\n",
- "hrhistory = [] # hierarchized recent history\n",
- "for i, row in rhistory.iterrows():\n",
- " inter_no = row.inter_no\n",
- " start_unix = row.start_unix\n",
- "\n",
- " ind = (timetable['start_seconds'] <= row.start_unix).sum() - 1\n",
- " start_hour = timetable.iloc[ind].start_hour\n",
- " start_minute = timetable.iloc[ind].start_minute\n",
- " isplit = isplits[(inter_no, start_hour, start_minute)]\n",
- " phas_As = [isplit[j][0] for j in isplit.keys()]\n",
- " phas_Bs = [isplit[j][1] for j in isplit.keys()]\n",
- " durs_A = row[[f'dura_A{j}' for j in range(1,9)]]\n",
- " durs_B = row[[f'dura_B{j}' for j in range(1,9)]]\n",
- " durations = []\n",
- " for j in range(1, len(isplit)+1):\n",
- " ja = isplit[j][0]\n",
- " jb = isplit[j][1]\n",
- " if ja == jb:\n",
- " durations.append(min(durs_A[ja-1], durs_B[jb-1]))\n",
- " else:\n",
- " durations.append(abs(durs_A[ja-1] - durs_B[ja-1]))\n",
- " new_rows = pd.DataFrame({'inter_no':[inter_no] * len(durations), 'start_unix':[start_unix] * len(durations),\n",
- " 'phas_A':phas_As, 'phas_B':phas_Bs, 'duration':durations})\n",
- " hrhistory.append(new_rows)\n",
- "hrhistory = pd.concat(hrhistory)\n",
- "hrhistory = hrhistory.sort_values(by = ['start_unix', 'inter_no', 'phas_A', 'phas_B']).reset_index(drop=True)\n",
- "\n",
- "# 5초단위로 수집한 이동류정보(time2movement[present_time])와 최근 1시간 신호이력(hrhistory)을 병합\n",
- "movedur = pd.merge(time2movement[present_time], hrhistory, how='inner', on=['inter_no', 'start_unix', 'phas_A', 'phas_B']) # movements and durations\n",
- "movedur = movedur.sort_values(by=['start_unix', 'inter_no', 'phas_A','phas_B'])\n",
- "movedur = movedur[['inter_no', 'start_unix', 'phas_A', 'phas_B', 'move_A', 'move_B', 'duration']]\n",
- "\n",
- "# 이동류 매칭 테이블에서 진입id, 진출id를 가져와서 붙임.\n",
- "for i, row in movedur.iterrows():\n",
- " inter_no = row.inter_no\n",
- " start_unix = row.start_unix\n",
- " # incoming and outgoing edges A\n",
- " move_A = row.move_A\n",
- " if move_A in [17, 18]:\n",
- " inc_edge_A = np.nan\n",
- " out_edge_A = np.nan\n",
- " else:\n",
- " match_A = matching[(matching.inter_no == inter_no) & (matching.move_no == move_A)].iloc[0]\n",
- " inc_edge_A = match_A.inc_edge\n",
- " out_edge_A = match_A.out_edge\n",
- " movedur.loc[i, ['inc_edge_A', 'out_edge_A']] = [inc_edge_A, out_edge_A]\n",
- " # incoming and outgoing edges B\n",
- " move_B = row.move_B\n",
- " if move_B in [17, 18]:\n",
- " inc_edge_B = np.nan\n",
- " out_edge_B = np.nan\n",
- " else:\n",
- " match_B = matching[(matching.inter_no == inter_no) & (matching.move_no == move_B)].iloc[0]\n",
- " inc_edge_B = match_B.inc_edge\n",
- " out_edge_B = match_B.out_edge\n",
- " movedur.loc[i, ['inc_edge_B', 'out_edge_B']] = [inc_edge_B, out_edge_B]\n",
- "\n",
- "# 이동류 컬럼 제거\n",
- "movedur = movedur.drop(['move_A', 'move_B'], axis=1)\n",
- "\n",
- "histid = movedur.copy() # history with edge ids (incoming and outgoing edge ids)\n",
- "histid['node_id'] = histid['inter_no'].map(inter2node)\n",
- "histid = histid[['inter_no', 'node_id', 'start_unix', 'phas_A', 'phas_B', 'duration', 'inc_edge_A', 'out_edge_A', 'inc_edge_B', 'out_edge_B']]\n",
- "histid = histid[histid.start_unix > present_time - 3600]\n",
- "# 시뮬레이션 시작시각 : 현재시각 - 600\n",
- "# 시뮬레이션 종료시각 : 현재시각 - 300\n",
- "# 현재시각 : present_time, PT\n",
- "# PT-900 ... PT-600 ... PT-300 ... PT\n",
- "histid"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "2024-01-05 04:10:00\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " node_id | \n",
- " start_unix | \n",
- " phas_A | \n",
- " phas_B | \n",
- " duration | \n",
- " inc_edge_A | \n",
- " out_edge_A | \n",
- " inc_edge_B | \n",
- " out_edge_B | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 176 | \n",
- " i1 | \n",
- " 1704391850 | \n",
- " 1 | \n",
- " 1 | \n",
- " 37 | \n",
- " -571542810_01 | \n",
- " -571542797_02.99 | \n",
- " 571542797_02.99 | \n",
- " 571542810_01 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 176 | \n",
- " i1 | \n",
- " 1704391850 | \n",
- " 2 | \n",
- " 2 | \n",
- " 73 | \n",
- " -571542810_01 | \n",
- " -571542797_02.99 | \n",
- " -571542810_01 | \n",
- " 571543469_01 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 176 | \n",
- " i1 | \n",
- " 1704391850 | \n",
- " 3 | \n",
- " 3 | \n",
- " 40 | \n",
- " 571543469_02 | \n",
- " -571542797_02.99 | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 178 | \n",
- " i3 | \n",
- " 1704391880 | \n",
- " 1 | \n",
- " 1 | \n",
- " 38 | \n",
- " 571540304_02 | \n",
- " 571556450_01 | \n",
- " 571556450_02 | \n",
- " 571540304_01 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 178 | \n",
- " i3 | \n",
- " 1704391880 | \n",
- " 2 | \n",
- " 2 | \n",
- " 39 | \n",
- " 571556450_02 | \n",
- " 571500475_01 | \n",
- " 571540304_02 | \n",
- " 571540303_01 | \n",
- "
\n",
- " \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- "
\n",
- " \n",
- " 528 | \n",
- " 201 | \n",
- " i8 | \n",
- " 1704395250 | \n",
- " 1 | \n",
- " 1 | \n",
- " 24 | \n",
- " -571500569_01 | \n",
- " 571500583_02 | \n",
- " -571500569_01 | \n",
- " 571500618_01 | \n",
- "
\n",
- " \n",
- " 529 | \n",
- " 201 | \n",
- " i8 | \n",
- " 1704395250 | \n",
- " 2 | \n",
- " 2 | \n",
- " 24 | \n",
- " 571500618_02 | \n",
- " 571500583_02 | \n",
- " 571500618_02 | \n",
- " 571500617_01 | \n",
- "
\n",
- " \n",
- " 530 | \n",
- " 201 | \n",
- " i8 | \n",
- " 1704395250 | \n",
- " 3 | \n",
- " 3 | \n",
- " 17 | \n",
- " 571500617_02 | \n",
- " 571500618_01 | \n",
- " 571500618_02 | \n",
- " 571500617_01 | \n",
- "
\n",
- " \n",
- " 531 | \n",
- " 201 | \n",
- " i8 | \n",
- " 1704395250 | \n",
- " 4 | \n",
- " 4 | \n",
- " 58 | \n",
- " 571500617_02 | \n",
- " 571500618_01 | \n",
- " 571500617_02 | \n",
- " 571500569_01 | \n",
- "
\n",
- " \n",
- " 532 | \n",
- " 201 | \n",
- " i8 | \n",
- " 1704395250 | \n",
- " 5 | \n",
- " 5 | \n",
- " 17 | \n",
- " 571500583_01 | \n",
- " 571500617_01 | \n",
- " 571500583_01 | \n",
- " 571500569_01 | \n",
- "
\n",
- " \n",
- "
\n",
- "
533 rows × 10 columns
\n",
- "
"
- ],
- "text/plain": [
- " inter_no node_id start_unix phas_A phas_B duration inc_edge_A \\\n",
- "0 176 i1 1704391850 1 1 37 -571542810_01 \n",
- "1 176 i1 1704391850 2 2 73 -571542810_01 \n",
- "2 176 i1 1704391850 3 3 40 571543469_02 \n",
- "3 178 i3 1704391880 1 1 38 571540304_02 \n",
- "4 178 i3 1704391880 2 2 39 571556450_02 \n",
- ".. ... ... ... ... ... ... ... \n",
- "528 201 i8 1704395250 1 1 24 -571500569_01 \n",
- "529 201 i8 1704395250 2 2 24 571500618_02 \n",
- "530 201 i8 1704395250 3 3 17 571500617_02 \n",
- "531 201 i8 1704395250 4 4 58 571500617_02 \n",
- "532 201 i8 1704395250 5 5 17 571500583_01 \n",
- "\n",
- " out_edge_A inc_edge_B out_edge_B \n",
- "0 -571542797_02.99 571542797_02.99 571542810_01 \n",
- "1 -571542797_02.99 -571542810_01 571543469_01 \n",
- "2 -571542797_02.99 NaN NaN \n",
- "3 571556450_01 571556450_02 571540304_01 \n",
- "4 571500475_01 571540304_02 571540303_01 \n",
- ".. ... ... ... \n",
- "528 571500583_02 -571500569_01 571500618_01 \n",
- "529 571500583_02 571500618_02 571500617_01 \n",
- "530 571500618_01 571500618_02 571500617_01 \n",
- "531 571500618_01 571500617_02 571500569_01 \n",
- "532 571500617_01 571500583_01 571500569_01 \n",
- "\n",
- "[533 rows x 10 columns]"
- ]
- },
- "execution_count": 16,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "make_histid(50)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " end_unix | \n",
- " dura_A1 | \n",
- " dura_A2 | \n",
- " dura_A3 | \n",
- " dura_A4 | \n",
- " dura_A5 | \n",
- " dura_A6 | \n",
- " dura_A7 | \n",
- " dura_A8 | \n",
- " ... | \n",
- " dura_B3 | \n",
- " dura_B4 | \n",
- " dura_B5 | \n",
- " dura_B6 | \n",
- " dura_B7 | \n",
- " dura_B8 | \n",
- " cycle | \n",
- " offset | \n",
- " D_n | \n",
- " S_n | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 202 | \n",
- " 1704380540 | \n",
- " 39 | \n",
- " 101 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " ... | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 140 | \n",
- " 103 | \n",
- " 0 | \n",
- " 0 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 202 | \n",
- " 1704380680 | \n",
- " 39 | \n",
- " 101 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " ... | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 140 | \n",
- " 103 | \n",
- " 0 | \n",
- " 0 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 202 | \n",
- " 1704380820 | \n",
- " 39 | \n",
- " 101 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " ... | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 140 | \n",
- " 103 | \n",
- " 0 | \n",
- " 0 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 202 | \n",
- " 1704380960 | \n",
- " 39 | \n",
- " 101 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " ... | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 140 | \n",
- " 103 | \n",
- " 0 | \n",
- " 0 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 202 | \n",
- " 1704381100 | \n",
- " 39 | \n",
- " 101 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " ... | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 140 | \n",
- " 103 | \n",
- " 0 | \n",
- " 0 | \n",
- "
\n",
- " \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- "
\n",
- " \n",
- " 200 | \n",
- " 202 | \n",
- " 1704409679 | \n",
- " 46 | \n",
- " 114 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " ... | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 160 | \n",
- " 103 | \n",
- " 0 | \n",
- " 0 | \n",
- "
\n",
- " \n",
- " 201 | \n",
- " 202 | \n",
- " 1704409840 | \n",
- " 46 | \n",
- " 114 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " ... | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 160 | \n",
- " 103 | \n",
- " 0 | \n",
- " 0 | \n",
- "
\n",
- " \n",
- " 202 | \n",
- " 202 | \n",
- " 1704410000 | \n",
- " 46 | \n",
- " 114 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " ... | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 160 | \n",
- " 103 | \n",
- " 0 | \n",
- " 0 | \n",
- "
\n",
- " \n",
- " 203 | \n",
- " 202 | \n",
- " 1704410160 | \n",
- " 46 | \n",
- " 114 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " ... | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 160 | \n",
- " 103 | \n",
- " 0 | \n",
- " 0 | \n",
- "
\n",
- " \n",
- " 204 | \n",
- " 202 | \n",
- " 1704410320 | \n",
- " 46 | \n",
- " 114 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " ... | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 160 | \n",
- " 103 | \n",
- " 0 | \n",
- " 0 | \n",
- "
\n",
- " \n",
- "
\n",
- "
205 rows × 22 columns
\n",
- "
"
- ],
- "text/plain": [
- " inter_no end_unix dura_A1 dura_A2 dura_A3 dura_A4 dura_A5 \\\n",
- "0 202 1704380540 39 101 0 0 0 \n",
- "1 202 1704380680 39 101 0 0 0 \n",
- "2 202 1704380820 39 101 0 0 0 \n",
- "3 202 1704380960 39 101 0 0 0 \n",
- "4 202 1704381100 39 101 0 0 0 \n",
- ".. ... ... ... ... ... ... ... \n",
- "200 202 1704409679 46 114 0 0 0 \n",
- "201 202 1704409840 46 114 0 0 0 \n",
- "202 202 1704410000 46 114 0 0 0 \n",
- "203 202 1704410160 46 114 0 0 0 \n",
- "204 202 1704410320 46 114 0 0 0 \n",
- "\n",
- " dura_A6 dura_A7 dura_A8 ... dura_B3 dura_B4 dura_B5 dura_B6 \\\n",
- "0 0 0 0 ... 0 0 0 0 \n",
- "1 0 0 0 ... 0 0 0 0 \n",
- "2 0 0 0 ... 0 0 0 0 \n",
- "3 0 0 0 ... 0 0 0 0 \n",
- "4 0 0 0 ... 0 0 0 0 \n",
- ".. ... ... ... ... ... ... ... ... \n",
- "200 0 0 0 ... 0 0 0 0 \n",
- "201 0 0 0 ... 0 0 0 0 \n",
- "202 0 0 0 ... 0 0 0 0 \n",
- "203 0 0 0 ... 0 0 0 0 \n",
- "204 0 0 0 ... 0 0 0 0 \n",
- "\n",
- " dura_B7 dura_B8 cycle offset D_n S_n \n",
- "0 0 0 140 103 0 0 \n",
- "1 0 0 140 103 0 0 \n",
- "2 0 0 140 103 0 0 \n",
- "3 0 0 140 103 0 0 \n",
- "4 0 0 140 103 0 0 \n",
- ".. ... ... ... ... ... ... \n",
- "200 0 0 160 103 0 0 \n",
- "201 0 0 160 103 0 0 \n",
- "202 0 0 160 103 0 0 \n",
- "203 0 0 160 103 0 0 \n",
- "204 0 0 160 103 0 0 \n",
- "\n",
- "[205 rows x 22 columns]"
- ]
- },
- "execution_count": 16,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
- "m = 100\n",
- "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
- "present_time = fmins[m] # 현재시점\n",
+ "def make_match1():\n",
+ " '''\n",
+ " 설명 :\n",
+ " 신호 DB에는 매 초마다 이동류정보가 업데이트 된다. 그리고 이 이동류정보를 매 5초마다 불러와서 사용하게 된다.\n",
+ " '../../Data/tables/moves/'에는 5초마다의 이동류정보가 저장되어 있다.\n",
"\n",
- "# 1. 신호이력 데이터 수집\n",
- "rhistory = history.copy()[(history.end_unix < present_time)]\n",
- "rhistory = rhistory.reset_index(drop=True)\n",
- "hours = np.array(range(midnight, next_day + 1, 3600))\n",
- "rhist = rhistory.copy()[rhistory.inter_no == inter_no] # 특정한 inter_no\n",
- "rhist = rhist.reset_index(drop=True)\n",
- "rhist['D_n'] = 0 # D_n : 시간차이\n",
- "rhist['S_n'] = 0 # S_n : 현시시간합\n",
- "rhist"
+ " return : 통합된 이동류정보\n",
+ " - 모든 inter_no(교차로번호)에 대한 A, B링 현시별 이동류정보\n",
+ " '''\n",
+ " # [이동류번호] 불러오기 (약 1분의 소요시간)\n",
+ " path_moves = '../../Data/tables/moves/'\n",
+ " csv_moves = os.listdir('../../Data/tables/moves/')\n",
+ " moves = [pd.read_csv(path_moves + csv_move, index_col=0) for csv_move in tqdm(csv_moves)]\n",
+ " match1 = pd.concat(moves).drop_duplicates().sort_values(by=['inter_no','phas_A','phas_B']).reset_index(drop=True)\n",
+ " match1.to_csv(path_moves + \"match1.csv\")\n",
+ " return match1"
]
},
{
"cell_type": "code",
- "execution_count": 43,
+ "execution_count": 3,
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "2024-01-05 08:19:00\n",
- "2024-01-05 07:20:20\n"
- ]
- }
- ],
+ "outputs": [],
"source": [
- "movement = time2movement[present_time]\n",
- "max_unix = movement.start_unix.max()\n",
- "min_unix = movement.start_unix.min()\n",
- "print(datetime.fromtimestamp(max_unix))\n",
- "print(datetime.fromtimestamp(min_unix))"
+ "def make_match2(match1):\n",
+ " '''\n",
+ " match1을 계층화함.\n",
+ " - match1의 컬럼 : inter_no, phas_A, phas_B, move_A, move_B\n",
+ " - match2의 컬럼 : inter_no, phase_no, ring_type, move_no\n",
+ " '''\n",
+ " # 계층화 (inter_no, phas_A, phas_B, move_A, move_B) -> ('inter_no', 'phase_no', 'ring_type', 'move_no')\n",
+ " matchA = match1[['inter_no', 'phas_A', 'move_A']].copy()\n",
+ " matchA.columns = ['inter_no', 'phase_no', 'move_no']\n",
+ " matchA['ring_type'] = 'A'\n",
+ " matchB = match1[['inter_no', 'phas_B', 'move_B']].copy()\n",
+ " matchB.columns = ['inter_no', 'phase_no', 'move_no']\n",
+ " matchB['ring_type'] = 'B'\n",
+ " match2 = pd.concat([matchA, matchB]).drop_duplicates()\n",
+ " match2 = match2[['inter_no', 'phase_no', 'ring_type', 'move_no']]\n",
+ " match2 = match2.sort_values(by=list(match2.columns))\n",
+ " return match2"
]
},
{
"cell_type": "code",
- "execution_count": 25,
+ "execution_count": 4,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " phas_A | \n",
- " phas_B | \n",
- " move_A | \n",
- " move_B | \n",
- " start_unix | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 201 | \n",
- " 1 | \n",
- " 1 | \n",
- " 8 | \n",
- " 3 | \n",
- " 1704406820 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 201 | \n",
- " 2 | \n",
- " 2 | \n",
- " 5 | \n",
- " 2 | \n",
- " 1704406820 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 201 | \n",
- " 3 | \n",
- " 3 | \n",
- " 6 | \n",
- " 2 | \n",
- " 1704406820 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 201 | \n",
- " 4 | \n",
- " 4 | \n",
- " 6 | \n",
- " 1 | \n",
- " 1704406820 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 201 | \n",
- " 5 | \n",
- " 5 | \n",
- " 7 | \n",
- " 4 | \n",
- " 1704406820 | \n",
- "
\n",
- " \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- "
\n",
- " \n",
- " 598 | \n",
- " 202 | \n",
- " 1 | \n",
- " 1 | \n",
- " 6 | \n",
- " 2 | \n",
- " 1704410320 | \n",
- "
\n",
- " \n",
- " 599 | \n",
- " 202 | \n",
- " 2 | \n",
- " 2 | \n",
- " 17 | \n",
- " 18 | \n",
- " 1704410320 | \n",
- "
\n",
- " \n",
- " 600 | \n",
- " 201 | \n",
- " 1 | \n",
- " 1 | \n",
- " 8 | \n",
- " 3 | \n",
- " 1704410340 | \n",
- "
\n",
- " \n",
- " 601 | \n",
- " 201 | \n",
- " 2 | \n",
- " 2 | \n",
- " 5 | \n",
- " 2 | \n",
- " 1704410340 | \n",
- "
\n",
- " \n",
- " 602 | \n",
- " 201 | \n",
- " 5 | \n",
- " 5 | \n",
- " 7 | \n",
- " 4 | \n",
- " 1704410340 | \n",
- "
\n",
- " \n",
- "
\n",
- "
603 rows × 6 columns
\n",
- "
"
- ],
- "text/plain": [
- " inter_no phas_A phas_B move_A move_B start_unix\n",
- "0 201 1 1 8 3 1704406820\n",
- "1 201 2 2 5 2 1704406820\n",
- "2 201 3 3 6 2 1704406820\n",
- "3 201 4 4 6 1 1704406820\n",
- "4 201 5 5 7 4 1704406820\n",
- ".. ... ... ... ... ... ...\n",
- "598 202 1 1 6 2 1704410320\n",
- "599 202 2 2 17 18 1704410320\n",
- "600 201 1 1 8 3 1704410340\n",
- "601 201 2 2 5 2 1704410340\n",
- "602 201 5 5 7 4 1704410340\n",
- "\n",
- "[603 rows x 6 columns]"
- ]
- },
- "execution_count": 25,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
+ "source": [
+ "def make_match3(match2):\n",
+ " '''\n",
+ " 각 movement들에 방향(진입방향, 진출방향)을 매칭시켜 추가함.\n",
+ " - match2의 컬럼 : inter_no, phase_no, ring_type, move_no\n",
+ " - match3의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir\n",
+ "\n",
+ " nema : \n",
+ " - 컬럼 : move_no, inc_dir, out_dir\n",
+ " - 모든 종류의 이동류번호에 대하여 진입방향과 진출방향을 매칭시키는 테이블\n",
+ " - 이동류번호 : 1 ~ 16, 17, 18, 21\n",
+ " - 진입, 진출방향(8방위) : 동, 서, 남, 북, 북동, 북서, 남동, 남서\n",
+ " '''\n",
+ " # nema 정보 불러오기 및 병합\n",
+ " nema = pd.read_csv('../../Data/tables/nema.csv', encoding='cp949')\n",
+ " match3 = pd.merge(match2, nema, how='left', on='move_no').drop_duplicates()\n",
+ " return match3"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
"source": [
- "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
- "present_time = fmins[m] # 현재시점\n",
- "print(datetime.fromtimestamp(present_time))\n",
+ "def make_match4(match3):\n",
+ " '''\n",
+ " 방위각 정보를 매칭시켜 추가함.\n",
+ " - match3의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir\n",
+ " - match4의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle\n",
+ "\n",
+ " angle_original : \n",
+ " - 컬럼 : inter_no, angle_Aj, angle_Bj (j : 1 ~ 8)\n",
+ " - 모든 종류의 이동류번호에 대하여 진입방향과 진출방향을 매칭시키는 테이블\n",
+ " - 이동류번호 : 1 ~ 16, 17, 18, 21\n",
+ " - 진입, 진출방향(8방위) : 동, 서, 남, 북, 북동, 북서, 남동, 남서\n",
+ " '''\n",
"\n",
- "Rhists = [] # Recent history (1시간 이내)\n",
- "for inter_no in history.inter_no.unique():\n",
- " # - 5분마다 신호이력 데이터 수집해서 통합테이블 생성할때\n",
- " # 1. 조회시점의 유닉스 타임을 기준으로 신호이력의 유닉스 타임이 1시간 이내인(Rhist) 데이터 수집\n",
- " rhistory = history.copy() # recent history\n",
- " rhistory = rhistory[(rhistory.end_unix < present_time)]\n",
- " hours = np.array(range(midnight, next_day + 1, 3600))\n",
- " rhist = rhistory.copy()[rhistory.inter_no == inter_no] # 특정한 inter_no\n",
- " rhist = rhist.reset_index(drop=True)\n",
- " new_rows = []\n",
- " # 1-1. 결측치 처리 : 인접한 두 end_unix의 차이가 계획된 주기의 두 배보다 크면 결측이 일어났다고 판단\n",
- " for n in range(len(rhist) - 1):\n",
- " curr_unix = rhist.iloc[n].end_unix # current end_unix\n",
- " next_unix = rhist.iloc[n+1].end_unix # next end_unix\n",
- " cycle = rhist.iloc[n].cycle\n",
- " if next_unix - curr_unix >= 2 * cycle:\n",
- " # 현재 unix를 계획된 주기만큼 늘려가면서 한 행씩 채워나간다.\n",
- " #(다음 unix와의 차이가 계획된 주기보다 작거나 같아질 때까지)\n",
- " while next_unix - curr_unix > cycle:\n",
- " curr_unix += cycle \n",
- " start_seconds = np.array(timetable.start_seconds)\n",
- " idx = (start_seconds <= curr_unix).sum() - 1\n",
- " start_hour = timetable.iloc[idx].start_hour\n",
- " start_minute = timetable.iloc[idx].start_minute\n",
- " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
- " prow = prow.drop(['start_hour', 'start_minute'], axis=1)\n",
- " prow['end_unix'] = curr_unix\n",
- " cycle = prow.iloc[0].cycle\n",
- " new_rows.append(prow)\n",
- " rhist = pd.concat([rhist] + new_rows).sort_values(['end_unix'])\n",
- " rhist = rhist.reset_index(drop=True)\n",
+ " # 방위각 정보 불러오기\n",
+ " dtype_dict = {f'angle_{alph}{j}':'str' for alph in ['A', 'B'] for j in range(1,9)}\n",
+ " angle_original = pd.read_csv('../../Data/tables/angle.csv', index_col=0, dtype = dtype_dict)\n",
+ "\n",
+ " # 계층화\n",
+ " angle = []\n",
+ " for i, row in angle_original.iterrows():\n",
+ " angle_codes = row[[f'angle_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " new = pd.DataFrame({'inter_no':[row.inter_no] * 16, 'phase_no':list(range(1, 9))*2, 'ring_type':['A'] * 8 + ['B'] * 8, 'angle_code':angle_codes.to_list()})\n",
+ " angle.append(new)\n",
+ " angle = pd.concat(angle)\n",
+ " angle = angle.dropna().reset_index(drop=True)\n",
+ "\n",
+ " # 병합\n",
+ " six_chars = angle.angle_code.apply(lambda x:len(x)==6)\n",
+ " angle.loc[six_chars,'inc_angle'] = angle.angle_code.apply(lambda x:x[:3])\n",
+ " angle.loc[six_chars,'out_angle'] = angle.angle_code.apply(lambda x:x[3:])\n",
+ " angle = angle.drop('angle_code', axis=1)\n",
+ " match4 = pd.merge(match3, angle, how='left', left_on=['inter_no', 'phase_no', 'ring_type'],\n",
+ " right_on=['inter_no', 'phase_no', 'ring_type']).drop_duplicates()\n",
+ " return match4"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_match5(match4):\n",
+ " '''\n",
+ " 진입엣지id, 진출엣지id, 노드id를 추가함 (주교차로).\n",
+ " - match4의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle\n",
+ " - match5의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle, inc_edge, out_edge, node_id\n",
+ " \n",
+ " 사용된 데이터 : \n",
+ " (1) net\n",
+ " - 성남시 정자동 부근의 샘플 네트워크\n",
+ " (2) inter_node\n",
+ " - 교차로번호와 노드id를 매칭시키는 테이블.\n",
+ " - parent/child 정보도 포함되어 있음\n",
+ " - 컬럼 : inter_no, node_id, inter_type\n",
+ " (3) inter_info\n",
+ " - 교차로 정보. 여기에서는 위도와 경도가 쓰임.\n",
+ " - 컬럼 : inter_no, inter_name, inter_lat, inter_lon, group_no, main_phase_no\n",
+ "\n",
+ " 진입엣지id, 진출엣지id를 얻는 과정 :\n",
+ " - match5 = match4.copy()의 각 열을 순회하면서 아래 과정을 반복함.\n",
+ " * 진입에 대해서만 서술하겠지만 진출도 마찬가지로 설명될 수 있음\n",
+ " - 해당 행의 교차로정보로부터 노드ID를 얻어내고, 해당 노드에 대한 모든 진출엣지id를 inc_edges에 저장.\n",
+ " * inc_edge(진입엣지) : incoming edge, out_edge(진출엣지) : outgoing_edge\n",
+ " - inc_edges의 모든 진입엣지에 대하여 진입방향(inc_dires, 2차원 단위벡터)을 얻어냄.\n",
+ " - 해당 행의 진입각으로부터 그에 대응되는 진입각방향(단위벡터)를 얻어냄.\n",
+ " - 주어진 진입각방향에 대하여 내적이 가장 작은 진입방향에 대한 진입엣지를 inc_edge_id로 지정함.\n",
+ " '''\n",
"\n",
- " # 1-2. 이상치 처리 : 기준유닉스로부터의 시간차이와 현시시간합이 11 이상 차이나면 이상치가 발생했다고 판단\n",
- " Rhist = rhist.copy() # recent history 1704393231\n",
- " Rhist = Rhist[(Rhist.end_unix >= present_time - 3600)] # Recent history (1시간 이내)\n",
- " Rhist = Rhist.reset_index(drop=True)\n",
- " Rhist['D_n'] = 0\n",
- " Rhist['S_n'] = 0\n",
- " for n in range(len(Rhist)):\n",
- " curr_unix = Rhist.iloc[n].end_unix # current end_unix\n",
- " cycle = Rhist.iloc[n].cycle\n",
- " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
- " end_unixes = rhist.end_unix.unique()\n",
- " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
- " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
- " # D_n : 시간차이\n",
- " D_n = curr_unix - base_unix\n",
- " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
- " # S_n : 현시시간합\n",
- " S_n = ddurations.values.sum() // 2\n",
- " Rhist.loc[n, ['D_n', 'S_n']] = [D_n, S_n]\n",
- " n = 1\n",
- " while n < len(Rhist):\n",
- " prev_unix = Rhist[Rhist.index==n-1]['end_unix'].iloc[0] # previous end_unix\n",
- " curr_unix = Rhist[Rhist.index==n]['end_unix'].iloc[0] # current end_unix\n",
- " R_n = (curr_unix - prev_unix) / cycle\n",
- " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
- " end_unixes = rhist.end_unix.unique()\n",
- " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
- " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
- " # D_n : 시간차이\n",
- " D_n = curr_unix - base_unix\n",
- " # S_n : 현시시간합\n",
- " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
- " S_n = ddurations.values.sum() // 2\n",
- " # 비율이 0.5보다 작거나 같으면 해당 행을 삭제\n",
- " if (abs(D_n - S_n) > 10) & (R_n <= 0.5):\n",
- " # print(\"lt\", inter_no, curr_unix, round(R_n,2), D_n, S_n)\n",
- " # display(Rhist.iloc[n])\n",
- " Rhist = Rhist.drop(index=n)\n",
- " n += 1\n",
- " # 행삭제에 따른 curr_unix, D_n, S_n 등 재정의\n",
- " if not Rhist[Rhist.index==n]['end_unix'].empty: # 마지막 행을 삭제하여 뒤의 행이 없을 때를 대비\n",
- " curr_unix = Rhist[Rhist.index==n]['end_unix'].iloc[0] # current end_unix\n",
- " R_n = (curr_unix - prev_unix) / cycle\n",
- " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
- " end_unixes = rhist.end_unix.unique()\n",
- " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
- " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
- " # D_n : 시간차이\n",
- " D_n = curr_unix - base_unix\n",
- " # S_n : 현시시간합\n",
- " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
- " S_n = ddurations.values.sum() // 2\n",
- " # 비율이 0.5보다 크면 해당 행 조정 (비율을 유지한 채로 현시시간 대체)\n",
- " if (abs(D_n - S_n) > 10) & (R_n > 0.5):\n",
- " start_seconds = np.array(timetable.start_seconds)\n",
- " idx = (start_seconds <= curr_unix).sum() - 1\n",
- " start_hour = timetable.iloc[idx].start_hour\n",
- " start_minute = timetable.iloc[idx].start_minute\n",
- " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)].copy().reset_index(drop=True).iloc[0] # planned row\n",
- " adjusted_dur = prow[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] * R_n\n",
- " # 조정된 현시시간을 정수로 바꿈\n",
- " int_parts = adjusted_dur.apply(lambda x: int(x))\n",
- " frac_parts = adjusted_dur - int_parts\n",
- " difference = int(round(adjusted_dur.sum())) - int_parts.sum()\n",
- " # 소수 부분이 가장 큰 상위 'difference'개의 값에 대해 올림 처리\n",
- " for _ in range(difference):\n",
- " max_frac_index = frac_parts.idxmax()\n",
- " int_parts[max_frac_index] += 1\n",
- " frac_parts[max_frac_index] = 0 # 이미 처리된 항목은 0으로 설정\n",
- " Rhist.loc[n, [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] = int_parts.values\n",
- " Rhist.loc[n, 'cycle'] = int_parts.sum() // 2\n",
- " # print(\"gt\", inter_no, curr_unix, round(R_n,2), D_n, S_n)\n",
- " n += 1\n",
- " Rhist = Rhist.drop(columns=['offset', 'D_n', 'S_n'])\n",
- " Rhists.append(Rhist)\n",
- "Rhists = pd.concat(Rhists)\n",
- "Rhists = Rhists.sort_values(by=['end_unix', 'inter_no']).reset_index(drop=True)"
+ " # 네트워크 불러오기 \n",
+ " net = sumolib.net.readNet('../../Data/networks/SN_sample.net.xml')\n",
+ " # 교차로-노드 매칭 정보 불러오기\n",
+ " inter_node = pd.read_csv('../../Data/tables/inter_node.csv', index_col=0)\n",
+ " # 교차로정보(위, 경도) 불러오기\n",
+ " inter_info = pd.read_csv('../../Data/tables/inter_info.csv', index_col=0)\n",
+ "\n",
+ " # parent node만 가져옴.\n",
+ " inter_node1 = inter_node[inter_node.inter_type == 'parent'].drop('inter_type', axis=1)\n",
+ " inter_info1 = inter_info[['inter_no', 'inter_lat', 'inter_lon']]\n",
+ " inter = pd.merge(inter_node1, inter_info1, how='left', left_on=['inter_no'],\n",
+ " right_on=['inter_no']).drop_duplicates()\n",
+ "\n",
+ " inter2node = dict(zip(inter['inter_no'], inter['node_id']))\n",
+ "\n",
+ " match5 = match4.copy()\n",
+ " # 진입진출ID 매칭\n",
+ " for index, row in match5.iterrows():\n",
+ " node_id = inter2node[row.inter_no]\n",
+ " node = net.getNode(node_id)\n",
+ " # 교차로의 모든 (from / to) edges\n",
+ " inc_edges = [edge for edge in node.getIncoming() if edge.getFunction() == ''] # incoming edges\n",
+ " out_edges = [edge for edge in node.getOutgoing() if edge.getFunction() == ''] # outgoing edges\n",
+ " # 교차로의 모든 (from / to) directions\n",
+ " inc_dirs = []\n",
+ " for inc_edge in inc_edges:\n",
+ " start = inc_edge.getShape()[-2]\n",
+ " end = inc_edge.getShape()[-1]\n",
+ " inc_dir = np.array(end) - np.array(start)\n",
+ " inc_dir = inc_dir / (inc_dir ** 2).sum() ** 0.5\n",
+ " inc_dirs.append(inc_dir)\n",
+ " out_dirs = []\n",
+ " for out_edge in out_edges:\n",
+ " start = out_edge.getShape()[0]\n",
+ " end = out_edge.getShape()[1]\n",
+ " out_dir = np.array(end) - np.array(start)\n",
+ " out_dir = out_dir / (out_dir ** 2).sum() ** 0.5\n",
+ " out_dirs.append(out_dir)\n",
+ " # 진입각, 진출각 불러오기\n",
+ " if not pd.isna(row.inc_angle):\n",
+ " inc_angle = int(row.inc_angle)\n",
+ " out_angle = int(row.out_angle)\n",
+ " # 방위각을 일반각으로 가공, 라디안 변환, 단위벡터로 변환\n",
+ " inc_angle = (-90 - inc_angle) % 360\n",
+ " inc_angle = inc_angle * np.pi / 180.\n",
+ " inc_dir_true = np.array([np.cos(inc_angle), np.sin(inc_angle)])\n",
+ " out_angle = (90 - out_angle) % 360\n",
+ " out_angle = out_angle * np.pi / 180.\n",
+ " out_dir_true = np.array([np.cos(out_angle), np.sin(out_angle)])\n",
+ " # 매칭 엣지 반환\n",
+ " inc_index = np.array([np.dot(inc_dir, inc_dir_true) for inc_dir in inc_dirs]).argmax()\n",
+ " out_index = np.array([np.dot(out_dir, out_dir_true) for out_dir in out_dirs]).argmax()\n",
+ " inc_edge_id = inc_edges[inc_index].getID()\n",
+ " out_edge_id = out_edges[out_index].getID()\n",
+ " match5.at[index, 'inc_edge'] = inc_edge_id\n",
+ " match5.at[index, 'out_edge'] = out_edge_id\n",
+ " match5['node_id'] = match5['inter_no'].map(inter2node)\n",
+ " match5 = match5.sort_values(by=['inter_no','phase_no','ring_type']).reset_index(drop=True)\n",
+ " return match5"
]
},
{
"cell_type": "code",
- "execution_count": 16,
+ "execution_count": 7,
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " start_hour | \n",
- " start_minute | \n",
- " start_seconds | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 1704380400 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 7 | \n",
- " 0 | \n",
- " 1704405600 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 9 | \n",
- " 0 | \n",
- " 1704412800 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 18 | \n",
- " 30 | \n",
- " 1704447000 | \n",
- "
\n",
- " \n",
- "
\n",
- "
"
- ],
- "text/plain": [
- " start_hour start_minute start_seconds\n",
- "0 0 0 1704380400\n",
- "1 7 0 1704405600\n",
- "2 9 0 1704412800\n",
- "3 18 30 1704447000"
- ]
- },
- "execution_count": 16,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
"source": [
- "# split, isplit : A,B 분리 혹은 통합시 사용될 수 있는 딕셔너리\n",
- "splits = {} # splits maps (inter_no, start_hour, start_minute) to split\n",
- "for i, row in plan.iterrows():\n",
- " inter_no = row.inter_no\n",
- " start_hour = row.start_hour\n",
- " start_minute = row.start_minute\n",
- " cycle = row.cycle\n",
- " cums_A = row[[f'dura_A{j}' for j in range(1,9)]].cumsum()\n",
- " cums_B = row[[f'dura_B{j}' for j in range(1,9)]].cumsum()\n",
- " splits[(inter_no, start_hour, start_minute)] = {} # split maps (phas_A, phas_B) to k\n",
- " k = 0\n",
- " for t in range(cycle):\n",
- " new_phas_A = len(cums_A[cums_A < t]) + 1\n",
- " new_phas_B = len(cums_B[cums_B < t]) + 1\n",
- " if k == 0 or ((new_phas_A, new_phas_B) != (phas_A, phas_B)):\n",
- " k += 1\n",
- " phas_A = new_phas_A\n",
- " phas_B = new_phas_B\n",
- " splits[(inter_no, start_hour, start_minute)][(phas_A, phas_B)] = k\n",
- "\n",
- "isplits = {} # the inverse of splits\n",
- "for i in splits:\n",
- " isplits[i] = {splits[i][k]:k for k in splits[i]} # isplit maps k to (phas_A, phas_B)\n",
+ "def make_match6(match5):\n",
+ " '''\n",
+ " 진입엣지id, 진출엣지id, 노드id를 추가함 (부교차로).\n",
+ " - match6의 컬럼 : inter_no, phase_no, ring_type, move_no, inc_dir, out_dir, inc_angle, out_angle, inc_edge, out_edge, node_id\n",
+ " \n",
+ " 사용된 데이터 : \n",
+ " (1) inter_node\n",
+ " - 교차로번호와 노드id를 매칭시키는 테이블.\n",
+ " - parent/child 정보도 포함되어 있음\n",
+ " - 컬럼 : inter_no, node_id, inter_type\n",
+ " (2) uturn (유턴정보)\n",
+ " - 컬럼 : parent_id, child_id, direction, condition, inc_edge, out_edge\n",
+ " - parent_id, child_id : 주교차로id, 유턴교차로id\n",
+ " - direction : 주교차로에 대한 유턴노드의 상대적인 위치(방향)\n",
+ " - condition : 좌회전시, 직진시, 직좌시, 보행신호시 중 하나\n",
+ " - inc_edge, out_edge : 유턴에 대한 진입진출엣지\n",
+ " (3) coord (연동교차로정보)\n",
+ " - 컬럼 : parent_id, child_id, phase_no, ring_type, inc_edge, out_edge\n",
+ " - parent_id, child_id : 주교차로id, 연동교차로id\n",
+ " - 나머지 컬럼 : 각 (현시, 링)별 진입진출엣지\n",
+ "\n",
+ " 설명 :\n",
+ " - match5는 주교차로에 대해서만 진입엣지id, 진출엣지id, 노드id를 추가했었음.\n",
+ " 여기에서 uturn, coord를 사용해서 부교차로들(유턴교차로, 연동교차로)에 대해서도 해당 값들을 부여함.\n",
+ " 유턴교차로 :\n",
+ " - directions를 정북기준 시계방향의 8방위로 정함.\n",
+ " - 이를 통해 진입방향이 주어진 경우에 좌회전, 직진, 보행 등에 대한 (진입방향, 진출방향)을 얻어낼 수 있음.\n",
+ " - 예) 진입방향(direction)이 '북'일 때, \n",
+ " - 직진 : (북, 남)\n",
+ " * 남 : directions[(ind + 4) % len(directions)]\n",
+ " - 좌회전 : (북, 동)\n",
+ " * 동 : directions[(ind + 2) % len(directions)]\n",
+ " - 보행 : (서, 동)\n",
+ " * 서 : directions[(ind - 2) % len(directions)]\n",
+ " - uturn의 각 행을 순회하면서 아래 과정을 반복함\n",
+ " - match5에서 parent_id에 해당하는 행들을 가져옴(cmatch).\n",
+ " - condition 별로 진입방향, 진출방향A, 진출방향B 정함.\n",
+ " - 상술한 directions를 활용하여 정함.\n",
+ " - (진입방향, 진출방향A, 진출방향B)을 고려하여 (현시, 링) 별로 진입엣지id, 진출엣지id를 정함.\n",
+ " - ex) cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " - 순회하면서 만든 cmatch를 cmatchs라는 리스트에 저장함.\n",
+ "\n",
+ " 연동교차로 :\n",
+ " - 연동교차로의 경우 coord에 (현시, 링)별 진입엣지ID, 진출엣지ID가 명시되어 있음.\n",
+ " - 'inc_dir', 'out_dir', 'inc_angle','out_angle'와 같은 열들은 np.nan을 지정해놓음.\n",
+ " - 이 열들은, 사실상 다음 스텝부터는 사용되지 않는 열들이기 때문에 np.nan으로 지정해놓아도 문제없음.\n",
+ "\n",
+ " match6 :\n",
+ " - 이렇게 얻은 match5, cmatchs, coord를 모두 pd.concat하여 match6을 얻어냄.\n",
+ " '''\n",
"\n",
- "# timetable\n",
- "timetable = plan[['start_hour', 'start_minute']].drop_duplicates()\n",
- "timetable['start_seconds'] = midnight + timetable['start_hour'] * 3600 + timetable['start_minute'] * 60\n",
- "timetable"
+ " inter_node = pd.read_csv('../../Data/tables/inter_node.csv', index_col=0)\n",
+ " node2inter = dict(zip(inter_node['node_id'], inter_node['inter_no']))\n",
+ "\n",
+ " uturn = pd.read_csv('../../Data/tables/child_uturn.csv')\n",
+ " coord = pd.read_csv('../../Data/tables/child_coord.csv')\n",
+ " child_ids = inter_node[inter_node.inter_type=='child'].node_id.unique()\n",
+ " ch2pa = {} # child to parent\n",
+ " for child_id in child_ids:\n",
+ " parent_no = inter_node[inter_node.node_id==child_id].inter_no.iloc[0]\n",
+ " sub_inter_node = inter_node[inter_node.inter_no==parent_no]\n",
+ " ch2pa[child_id] = sub_inter_node[sub_inter_node.inter_type=='parent'].iloc[0].node_id\n",
+ " directions = ['북', '북동', '동', '남동', '남', '남서', '서', '북서'] # 정북기준 시계방향으로 8방향\n",
+ "\n",
+ " # 각 uturn node에 대하여 (inc_edge_id, out_edge_id) 부여\n",
+ " cmatches = []\n",
+ " for _, row in uturn.iterrows():\n",
+ " child_id = row.child_id\n",
+ " parent_id = row.parent_id\n",
+ " direction = row.direction\n",
+ " condition = row.condition\n",
+ " inc_edge_id = row.inc_edge\n",
+ " out_edge_id = row.out_edge\n",
+ " # match5에서 parent_id에 해당하는 행들을 가져옴\n",
+ " cmatch = match5.copy()[match5.node_id==parent_id] # match dataframe for a child node\n",
+ " cmatch = cmatch.sort_values(by=['phase_no', 'ring_type']).reset_index(drop=True)\n",
+ " cmatch['node_id'] = child_id\n",
+ " cmatch[['inc_edge', 'out_edge']] = np.nan\n",
+ "\n",
+ " # condition 별로 inc_dire, out_dire_A, out_dire_B를 정함\n",
+ " ind = directions.index(direction)\n",
+ " if condition == \"좌회전시\":\n",
+ " inc_dire = direction\n",
+ " out_dire_A = out_dire_B = directions[(ind + 2) % len(directions)]\n",
+ " elif condition == \"직진시\":\n",
+ " inc_dire = direction\n",
+ " out_dire_A = out_dire_B = directions[(ind + 4) % len(directions)]\n",
+ " elif condition == \"직좌시\":\n",
+ " inc_dire = direction\n",
+ " out_dire_A = directions[(ind + 2) % len(directions)]\n",
+ " out_dire_B = directions[(ind + 4) % len(directions)]\n",
+ " elif condition == \"보행신호시\":\n",
+ " inc_dire = directions[(ind + 2) % len(directions)]\n",
+ " out_dire_A = directions[(ind - 2) % len(directions)]\n",
+ " out_dire_B = directions[(ind - 2) % len(directions)]\n",
+ "\n",
+ " # (inc_dire, out_dire_A, out_dire_B) 별로 inc_edge_id, out_edge_id를 정함\n",
+ " if condition == '직좌시':\n",
+ " ap = cmatch[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A)].phase_no.iloc[0]\n",
+ " bp = cmatch[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B)].phase_no.iloc[0]\n",
+ " # 직진과 좌회전이 같은 현시에 있는 경우에만 (inc_edge_id, out_edge_id)를 부여한다.\n",
+ " if ap == bp:\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " elif condition == '보행신호시':\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " # 이동류번호가 17(보행신호)이면서 유턴노드방향으로 가는 신호가 없으면 (inc_edge_id, out_edge_id)를 부여한다.\n",
+ " cmatch.loc[(cmatch.move_no==17) & (cmatch.out_dir!=direction), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " else: # '직진시', '좌회전시'\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), ['inc_edge', 'out_edge']] = [inc_edge_id, out_edge_id]\n",
+ " # 유턴신호의 이동류번호를 19로 부여한다.\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_A), 'move_no'] = 19\n",
+ " cmatch.loc[(cmatch.inc_dir==inc_dire) & (cmatch.out_dir==out_dire_B), 'move_no'] = 19\n",
+ " cmatches.append(cmatch)\n",
+ "\n",
+ " # 각 coordination node에 대하여 (inc_edge_id, out_edge_id) 부여\n",
+ " coord['inter_no'] = coord['parent_id'].map(node2inter)\n",
+ " coord = coord.rename(columns={'child_id':'node_id'})\n",
+ " coord[['inc_dir', 'out_dir', 'inc_angle','out_angle']] = np.nan\n",
+ " coord['move_no'] = 20\n",
+ " coord = coord[['inter_no', 'phase_no', 'ring_type', 'move_no', 'inc_dir', 'out_dir', 'inc_angle','out_angle', 'inc_edge', 'out_edge', 'node_id']]\n",
+ " \n",
+ " # display(coord)\n",
+ " cmatches = pd.concat(cmatches)\n",
+ " match6 = pd.concat([match5, cmatches, coord]).drop_duplicates().sort_values(by=['inter_no', 'node_id', 'phase_no', 'ring_type'])\n",
+ " # with pd.option_context('display.max_rows', None, 'display.max_columns', None):\n",
+ " match6.to_csv('../../Data/tables/matching/match6.csv')\n",
+ " return match6"
]
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
- "def make_rhistory(m:int):\n",
- " '''\n",
- " input : m\n",
- " - m ranges from 0 to 287, but 0 makes an error where 288 = 86400//300\n",
- " - present_time = fmins[m] : 현재시점\n",
- " + fmins[m-2] : 시뮬레이션 시작시점\n",
- " + fmins[m-1] : 시뮬레이션 종료시점\n",
- " output : rhistory\n",
- " - recent history\n",
- " - 현재시각(present_time) 이전 1시간 동안의 신호이력에 대하여 결측치 및 이상치를 처리한 결과\n",
- " - 교차로번호(inter_no), 종료유닉스(end_unix), 현시시간(dur_Aj, dur_Bj), 주기(cycle), 옵셋(offset)\n",
+ "def make_matching(match6):\n",
" '''\n",
- " fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
- " present_time = fmins[m] # 현재시점\n",
- " print(datetime.fromtimestamp(present_time))\n",
- "\n",
- " Rhists = [] # Recent history (1시간 이내)\n",
- " for inter_no in history.inter_no.unique():\n",
- " # - 5분마다 신호이력 데이터 수집해서 통합테이블 생성할때\n",
- " # 1. 조회시점의 유닉스 타임을 기준으로 신호이력의 유닉스 타임이 1시간 이내인(Rhist) 데이터 수집\n",
- " rhistory = history.copy() # recent history\n",
- " rhistory = rhistory[(rhistory.end_unix < present_time)]\n",
- " hours = np.array(range(midnight, next_day + 1, 3600))\n",
- " rhist = rhistory.copy()[rhistory.inter_no == inter_no] # 특정한 inter_no\n",
- " rhist = rhist.reset_index(drop=True)\n",
- " new_rows = []\n",
- " # 1-1. 결측치 처리 : 인접한 두 end_unix의 차이가 계획된 주기의 두 배보다 크면 결측이 일어났다고 판단\n",
- " for n in range(len(rhist) - 1):\n",
- " curr_unix = rhist.iloc[n].end_unix # current end_unix\n",
- " next_unix = rhist.iloc[n+1].end_unix # next end_unix\n",
- " cycle = rhist.iloc[n].cycle\n",
- " if next_unix - curr_unix >= 2 * cycle:\n",
- " # 현재 unix를 계획된 주기만큼 늘려가면서 한 행씩 채워나간다.\n",
- " #(다음 unix와의 차이가 계획된 주기보다 작거나 같아질 때까지)\n",
- " while next_unix - curr_unix > cycle:\n",
- " curr_unix += cycle\n",
- " start_seconds = np.array(timetable.start_seconds)\n",
- " idx = (start_seconds <= curr_unix).sum() - 1\n",
- " start_hour = timetable.iloc[idx].start_hour\n",
- " start_minute = timetable.iloc[idx].start_minute\n",
- " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
- " prow = prow.drop(['start_hour', 'start_minute'], axis=1)\n",
- " prow['end_unix'] = curr_unix\n",
- " cycle = prow.iloc[0].cycle\n",
- " new_rows.append(prow)\n",
- " rhist = pd.concat([rhist] + new_rows).sort_values(['end_unix'])\n",
- " rhist = rhist.reset_index(drop=True)\n",
- "\n",
- " # 1-2. 이상치 처리 : 기준유닉스로부터의 시간차이와 현시시간합이 11 이상 차이나면 이상치가 발생했다고 판단\n",
- " Rhist = rhist.copy() # recent history 1704393231\n",
- " Rhist = Rhist[(Rhist.end_unix >= present_time - 3600)] # Recent history (1시간 이내)\n",
- " Rhist = Rhist.reset_index(drop=True)\n",
- " Rhist['D_n'] = 0\n",
- " Rhist['S_n'] = 0\n",
- " for n in range(len(Rhist)):\n",
- " curr_unix = Rhist.iloc[n].end_unix # current end_unix\n",
- " cycle = Rhist.iloc[n].cycle\n",
- " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
- " end_unixes = rhist.end_unix.unique()\n",
- " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
- " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
- " # D_n : 시간차이\n",
- " D_n = curr_unix - base_unix\n",
- " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
- " # S_n : 현시시간합\n",
- " S_n = ddurations.values.sum() // 2\n",
- " Rhist.loc[n, ['D_n', 'S_n']] = [D_n, S_n]\n",
- " n = 1\n",
- " while n < len(Rhist):\n",
- " prev_unix = Rhist[Rhist.index==n-1]['end_unix'].iloc[0] # previous end_unix\n",
- " curr_unix = Rhist[Rhist.index==n]['end_unix'].iloc[0] # current end_unix\n",
- " R_n = (curr_unix - prev_unix) / cycle\n",
- " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
- " end_unixes = rhist.end_unix.unique()\n",
- " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
- " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
- " # D_n : 시간차이\n",
- " D_n = curr_unix - base_unix\n",
- " # S_n : 현시시간합\n",
- " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
- " S_n = ddurations.values.sum() // 2\n",
- " # 비율이 0.5보다 작거나 같으면 해당 행을 삭제\n",
- " if (abs(D_n - S_n) > 10) & (R_n <= 0.5):\n",
- " Rhist = Rhist.drop(index=n)\n",
- " n += 1\n",
- " # 행삭제에 따른 curr_unix, D_n, S_n 등 재정의\n",
- " if not Rhist[Rhist.index==n]['end_unix'].empty: # 마지막 행을 삭제하여 뒤의 행이 없을 때를 대비\n",
- " curr_unix = Rhist[Rhist.index==n]['end_unix'].iloc[0] # current end_unix\n",
- " R_n = (curr_unix - prev_unix) / cycle\n",
- " ghour_lt_curr_unix = hours[hours < curr_unix].max() # the greatest hour less than curr_unix\n",
- " end_unixes = rhist.end_unix.unique()\n",
- " end_unixes_lt_ghour = np.sort(end_unixes[end_unixes < ghour_lt_curr_unix]) # end unixes less than ghour_lt_end_unix\n",
- " base_unix = end_unixes_lt_ghour[-5] # 기준유닉스 : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 end_unix\n",
- " # D_n : 시간차이\n",
- " D_n = curr_unix - base_unix\n",
- " # S_n : 현시시간합\n",
- " ddurations = rhist[(rhist.end_unix > base_unix) & (rhist.end_unix <= curr_unix)][[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
- " S_n = ddurations.values.sum() // 2\n",
- " # 비율이 0.5보다 크면 해당 행 조정 (비율을 유지한 채로 현시시간 대체)\n",
- " if (abs(D_n - S_n) > 10) & (R_n > 0.5):\n",
- " start_seconds = np.array(timetable.start_seconds)\n",
- " idx = (start_seconds <= curr_unix).sum() - 1\n",
- " start_hour = timetable.iloc[idx].start_hour\n",
- " start_minute = timetable.iloc[idx].start_minute\n",
- " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)].copy().reset_index(drop=True).iloc[0] # planned row\n",
- " adjusted_dur = prow[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] * R_n\n",
- " # 조정된 현시시간을 정수로 바꿈\n",
- " int_parts = adjusted_dur.apply(lambda x: int(x))\n",
- " frac_parts = adjusted_dur - int_parts\n",
- " difference = int(round(adjusted_dur.sum())) - int_parts.sum()\n",
- " # 소수 부분이 가장 큰 상위 'difference'개의 값에 대해 올림 처리\n",
- " for _ in range(difference):\n",
- " max_frac_index = frac_parts.idxmax()\n",
- " int_parts[max_frac_index] += 1\n",
- " frac_parts[max_frac_index] = 0 # 이미 처리된 항목은 0으로 설정\n",
- " Rhist.loc[n, [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] = int_parts.values\n",
- " Rhist.loc[n, 'cycle'] = int_parts.sum() // 2\n",
- " n += 1\n",
- " Rhist = Rhist.drop(columns=['offset', 'D_n', 'S_n'])\n",
- " Rhists.append(Rhist)\n",
- " Rhists = pd.concat(Rhists)\n",
- " Rhists = Rhists.sort_values(by=['end_unix', 'inter_no']).reset_index(drop=True)\n",
- " return Rhists"
+ " 이동류 매칭 : 각 교차로에 대하여, 가능한 모든 이동류 (1~18, 21)에 대한 진입·진출엣지ID를 지정한다.\n",
+ " 모든 이동류에 대해 지정하므로, 시차제시 이전과 다른 이동류가 등장하더라도 항상 진입·진출 엣지 ID를 지정할 수 있다. \n",
+ " - matching의 컬럼 : inter_no, move_no, inc_dir, out_dir, inc_edge, out_edge, node_id\n",
+ " \n",
+ " 설명 : \n",
+ " - 필요한 리스트, 딕셔너리 등을 정의\n",
+ " (1) 가능한 (진입방향, 진출방향) 목록 [리스트]\n",
+ " (2) 각 교차로별 방향 목록 : pdires (possible directions) [딕셔너리]\n",
+ " (3) 각 (교차로, 진입방향) 별 진입id 목록 : inc2id (incoming direction to incoming edge_id) [딕셔너리]\n",
+ " (4) 각 (교차로, 진출방향) 별 진출id 목록 : out2id (outgoing direction to outgoing edge_id) [딕셔너리]\n",
+ " (5) 각 교차로별 가능한 (진입방향, 진출방향) 목록 : pflow (possible flows) [딕셔너리]\n",
+ " - matching은 빈 리스트로 지정.\n",
+ " - 모든 노드id에 대하여 다음 과정을 반복\n",
+ " - 해당 노드id에 대한 모든 가능한 (진입방향, 진출방향)에 대하여 다음 과정을 반복\n",
+ " - (노드id, 진입방향)으로부터 진입엣지id를 얻어냄. 마찬가지로 진출엣지id도 얻어냄\n",
+ " - 얻어낸 정보를 바탕으로 한 행(new_row)을 만들고 이것을 matching에 append\n",
+ " '''\n",
+ "\n",
+ " match7 = match6.copy()\n",
+ " match7 = match7[['inter_no', 'move_no', 'inc_dir', 'out_dir', 'inc_edge', 'out_edge', 'node_id']]\n",
+ " inter_node = pd.read_csv('../../Data/tables/inter_node.csv', index_col=0)\n",
+ " nema = pd.read_csv('../../Data/tables/nema.csv', encoding='cp949')\n",
+ "\n",
+ " parent_ids = sorted(inter_node[inter_node.inter_type=='parent'].node_id.unique())\n",
+ " child_ids = sorted(inter_node[inter_node.inter_type=='child'].node_id.unique())\n",
+ "\n",
+ " # (1) 가능한 (진입방향, 진출방향) 목록 \n",
+ " flows = nema.dropna().apply(lambda row: (row['inc_dir'], row['out_dir']), axis=1).tolist()\n",
+ " # (2) 각 교차로별 방향 목록 : pdires (possible directions)\n",
+ " pdires = {}\n",
+ " for node_id in parent_ids:\n",
+ " dires = match7[match7.node_id == node_id][['inc_dir','out_dir']].values.flatten()\n",
+ " dires = {dire for dire in dires if type(dire)==str}\n",
+ " pdires[node_id] = dires\n",
+ " # (3) 각 (교차로, 진입방향) 별 진입id 목록 : inc2id (incoming direction to incoming edge_id)\n",
+ " inc2id = {}\n",
+ " for node_id in parent_ids:\n",
+ " for inc_dir in pdires[node_id]:\n",
+ " df = match7[(match7.node_id==node_id) & (match7.inc_dir==inc_dir)]\n",
+ " inc2id[(node_id, inc_dir)] = df.inc_edge.iloc[0]\n",
+ " # (4) 각 (교차로, 진출방향) 별 진출id 목록 : out2id (outgoing direction to outgoing edge_id)\n",
+ " out2id = {}\n",
+ " for node_id in parent_ids:\n",
+ " for out_dir in pdires[node_id]:\n",
+ " df = match7[(match7.node_id==node_id) & (match7.out_dir==out_dir)]\n",
+ " out2id[(node_id, out_dir)] = df.out_edge.iloc[0]\n",
+ " # (5) 각 교차로별 가능한 (진입방향, 진출방향) 목록 : pflow (possible flows)\n",
+ " pflow = {}\n",
+ " for node_id in parent_ids:\n",
+ " pflow[node_id] = [flow for flow in flows if set(flow).issubset(pdires[node_id])]\n",
+ " # (6) 가능한 이동류에 대하여 진입id, 진출id 배정 : matching\n",
+ " node2inter = dict(zip(match7['node_id'], match7['inter_no']))\n",
+ " dires_right = ['북', '서', '남', '동', '북'] # ex (북, 서), (서, 남) 등은 우회전 flow\n",
+ " matching = []\n",
+ " for node_id in parent_ids:\n",
+ " inter_no = node2inter[node_id]\n",
+ " # 좌회전과 직진(1 ~ 16)\n",
+ " for (inc_dir, out_dir) in pflow[node_id]:\n",
+ " move_no = nema[(nema.inc_dir==inc_dir) & (nema.out_dir==out_dir)].move_no.iloc[0]\n",
+ " inc_edge = inc2id[(node_id, inc_dir)]\n",
+ " out_edge = out2id[(node_id, out_dir)]\n",
+ " new_row = pd.DataFrame({'inter_no':[inter_no], 'move_no':[move_no],\n",
+ " 'inc_dir':[inc_dir], 'out_dir':[out_dir],\n",
+ " 'inc_edge':[inc_edge], 'out_edge':[out_edge], 'node_id':[node_id]})\n",
+ " matching.append(new_row)\n",
+ " # 보행신호(17), 전적색(18)\n",
+ " new_row = pd.DataFrame({'inter_no':[inter_no] * 2, 'move_no':[17, 18],\n",
+ " 'inc_dir':[None]*2, 'out_dir':[None]*2,\n",
+ " 'inc_edge':[None]*2, 'out_edge':[None]*2, 'node_id':[node_id]*2})\n",
+ " matching.append(new_row)\n",
+ " # 신호우회전(21)\n",
+ " for d in range(len(dires_right)-1):\n",
+ " inc_dir = dires_right[d]\n",
+ " out_dir = dires_right[d+1]\n",
+ " if {inc_dir, out_dir}.issubset(pdires[node_id]):\n",
+ " inc_edge = inc2id[(node_id, inc_dir)]\n",
+ " out_edge = out2id[(node_id, out_dir)]\n",
+ " new_row = pd.DataFrame({'inter_no':[inter_no], 'move_no':[21],\n",
+ " 'inc_dir':[inc_dir], 'out_dir':[out_dir],\n",
+ " 'inc_edge':[inc_edge], 'out_edge':[out_edge], 'node_id':[node_id]})\n",
+ " matching.append(new_row)\n",
+ " matching.append(match7[match7.node_id.isin(child_ids)])\n",
+ " matching = pd.concat(matching)\n",
+ " matching = matching.dropna().sort_values(by=['inter_no', 'node_id', 'move_no']).reset_index(drop=True)\n",
+ " matching['move_no'] = matching['move_no'].astype(int)\n",
+ " matching.to_csv('../../Data/tables/matching/matching.csv')\n",
+ " return matching"
]
},
{
"cell_type": "code",
- "execution_count": 30,
+ "execution_count": 9,
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "2024-01-05 08:20:00\n"
- ]
- },
- {
- "data": {
- "text/html": [
- "\n",
- "\n",
- "
\n",
- " \n",
- " \n",
- " | \n",
- " inter_no | \n",
- " end_unix | \n",
- " dura_A1 | \n",
- " dura_A2 | \n",
- " dura_A3 | \n",
- " dura_A4 | \n",
- " dura_A5 | \n",
- " dura_A6 | \n",
- " dura_A7 | \n",
- " dura_A8 | \n",
- " dura_B1 | \n",
- " dura_B2 | \n",
- " dura_B3 | \n",
- " dura_B4 | \n",
- " dura_B5 | \n",
- " dura_B6 | \n",
- " dura_B7 | \n",
- " dura_B8 | \n",
- " cycle | \n",
- "
\n",
- " \n",
- " \n",
- " \n",
- " 0 | \n",
- " 201 | \n",
- " 1704406820 | \n",
- " 30 | \n",
- " 36 | \n",
- " 18 | \n",
- " 58 | \n",
- " 18 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 30 | \n",
- " 36 | \n",
- " 18 | \n",
- " 58 | \n",
- " 18 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 160 | \n",
- "
\n",
- " \n",
- " 1 | \n",
- " 177 | \n",
- " 1704406830 | \n",
- " 40 | \n",
- " 25 | \n",
- " 71 | \n",
- " 34 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 40 | \n",
- " 25 | \n",
- " 71 | \n",
- " 34 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 170 | \n",
- "
\n",
- " \n",
- " 2 | \n",
- " 210 | \n",
- " 1704406850 | \n",
- " 43 | \n",
- " 39 | \n",
- " 65 | \n",
- " 23 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 24 | \n",
- " 58 | \n",
- " 65 | \n",
- " 23 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 170 | \n",
- "
\n",
- " \n",
- " 3 | \n",
- " 175 | \n",
- " 1704406870 | \n",
- " 40 | \n",
- " 42 | \n",
- " 55 | \n",
- " 33 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 40 | \n",
- " 42 | \n",
- " 29 | \n",
- " 59 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 170 | \n",
- "
\n",
- " \n",
- " 4 | \n",
- " 176 | \n",
- " 1704406910 | \n",
- " 37 | \n",
- " 93 | \n",
- " 40 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 37 | \n",
- " 93 | \n",
- " 40 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 170 | \n",
- "
\n",
- " \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- " ... | \n",
- "
\n",
- " \n",
- " 146 | \n",
- " 175 | \n",
- " 1704410269 | \n",
- " 40 | \n",
- " 42 | \n",
- " 55 | \n",
- " 33 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 40 | \n",
- " 42 | \n",
- " 29 | \n",
- " 59 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 170 | \n",
- "
\n",
- " \n",
- " 147 | \n",
- " 176 | \n",
- " 1704410310 | \n",
- " 37 | \n",
- " 93 | \n",
- " 40 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 37 | \n",
- " 93 | \n",
- " 40 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 170 | \n",
- "
\n",
- " \n",
- " 148 | \n",
- " 178 | \n",
- " 1704410310 | \n",
- " 38 | \n",
- " 39 | \n",
- " 42 | \n",
- " 41 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 38 | \n",
- " 39 | \n",
- " 62 | \n",
- " 21 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 160 | \n",
- "
\n",
- " \n",
- " 149 | \n",
- " 202 | \n",
- " 1704410320 | \n",
- " 46 | \n",
- " 114 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 46 | \n",
- " 114 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 160 | \n",
- "
\n",
- " \n",
- " 150 | \n",
- " 201 | \n",
- " 1704410340 | \n",
- " 30 | \n",
- " 36 | \n",
- " 18 | \n",
- " 58 | \n",
- " 18 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 30 | \n",
- " 36 | \n",
- " 18 | \n",
- " 58 | \n",
- " 18 | \n",
- " 0 | \n",
- " 0 | \n",
- " 0 | \n",
- " 160 | \n",
- "
\n",
- " \n",
- "
\n",
- "
151 rows × 19 columns
\n",
- "
"
- ],
- "text/plain": [
- " inter_no end_unix dura_A1 dura_A2 dura_A3 dura_A4 dura_A5 \\\n",
- "0 201 1704406820 30 36 18 58 18 \n",
- "1 177 1704406830 40 25 71 34 0 \n",
- "2 210 1704406850 43 39 65 23 0 \n",
- "3 175 1704406870 40 42 55 33 0 \n",
- "4 176 1704406910 37 93 40 0 0 \n",
- ".. ... ... ... ... ... ... ... \n",
- "146 175 1704410269 40 42 55 33 0 \n",
- "147 176 1704410310 37 93 40 0 0 \n",
- "148 178 1704410310 38 39 42 41 0 \n",
- "149 202 1704410320 46 114 0 0 0 \n",
- "150 201 1704410340 30 36 18 58 18 \n",
- "\n",
- " dura_A6 dura_A7 dura_A8 dura_B1 dura_B2 dura_B3 dura_B4 dura_B5 \\\n",
- "0 0 0 0 30 36 18 58 18 \n",
- "1 0 0 0 40 25 71 34 0 \n",
- "2 0 0 0 24 58 65 23 0 \n",
- "3 0 0 0 40 42 29 59 0 \n",
- "4 0 0 0 37 93 40 0 0 \n",
- ".. ... ... ... ... ... ... ... ... \n",
- "146 0 0 0 40 42 29 59 0 \n",
- "147 0 0 0 37 93 40 0 0 \n",
- "148 0 0 0 38 39 62 21 0 \n",
- "149 0 0 0 46 114 0 0 0 \n",
- "150 0 0 0 30 36 18 58 18 \n",
- "\n",
- " dura_B6 dura_B7 dura_B8 cycle \n",
- "0 0 0 0 160 \n",
- "1 0 0 0 170 \n",
- "2 0 0 0 170 \n",
- "3 0 0 0 170 \n",
- "4 0 0 0 170 \n",
- ".. ... ... ... ... \n",
- "146 0 0 0 170 \n",
- "147 0 0 0 170 \n",
- "148 0 0 0 160 \n",
- "149 0 0 0 160 \n",
- "150 0 0 0 160 \n",
- "\n",
- "[151 rows x 19 columns]"
- ]
- },
- "execution_count": 30,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
+ "outputs": [],
+ "source": [
+ "def matching_main():\n",
+ " match1 = pd.read_csv('../../Data/tables/moves/match1.csv', index_col=0)\n",
+ " match2 = make_match2(match1)\n",
+ " match3 = make_match3(match2)\n",
+ " match4 = make_match4(match3)\n",
+ " match5 = make_match5(match4)\n",
+ " match6 = make_match6(match5)\n",
+ " matching = make_matching(match6)\n",
+ " return matching\n",
+ "matching = matching_main()"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# B. 5초 간격으로 이동류번호 수집"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "# 5초 단위로 이동류번호 저장 및 신호이력에서 유닉스시각 가져와서 표시, 한시간동안의 데이터만 보관\n",
+ "midnight = int(datetime(2024, 1, 5, 0, 0, 0).timestamp())\n",
+ "next_day = int(datetime(2024, 1, 6, 0, 0, 0).timestamp())\n",
+ "fsecs = range(midnight, next_day, 5) # fsecs : unix time by Five SECondS\n",
+ "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def save_movement():\n",
+ " # time2move = dict(zip(fsecs,moves)) # move : 어느 순간의 이동류정보\n",
+ " history = pd.read_csv('../../Data/tables/history.csv', index_col=0)\n",
+ "\n",
+ " time2movement = {} # movement : 어느 순간의, 그 순간으로부터 한시간 동안의 (교차로번호 + 현시별이동류번호 + 시작시간)\n",
+ " # - 아래 절차를 5초마다 반복\n",
+ " for fsec in tqdm(fsecs): # fsec : unix time by Five SECond\n",
+ " # 1. 상태 테이블 조회해서 전체 데이터중 필요데이터(교차로번호, A링 현시번호, A링 이동류번호, B링 현시번호, B링 이동류번호)만 수집 : A\n",
+ " # move = time2move[fsec]\n",
+ " move = pd.read_csv(f'../../Data/tables/moves/move_{fsec}.csv', index_col=0)\n",
+ " # 2. 이력 테이블 조회해서 교차로별로 유닉스시간 최대인 데이터(교차로변호, 종료유닉스타임)만 수집 : B\n",
+ " recent_histories = [group.iloc[-1:] for _, group in history[history['end_unix'] < fsec].groupby('inter_no')] # 교차로별로 유닉스시간이 최대인 행들\n",
+ " if not recent_histories:\n",
+ " rhistory = pd.DataFrame({'inter_no':[], 'end_unix':[]}) # recent history\n",
+ " else:\n",
+ " rhistory = pd.concat(recent_histories)\n",
+ " recent_unix = rhistory[['inter_no', 'end_unix']]\n",
+ " # 3. 상태 테이블 조회정보(A)와 이력 테이블 조회정보(B) 조인(키값 : 교차로번호) : C\n",
+ " move = pd.merge(move, recent_unix, how='left', on='inter_no')\n",
+ " move['end_unix'] = move['end_unix'].fillna(0).astype(int)\n",
+ " move = move.drop_duplicates()\n",
+ " # 4. C데이터 프레임에 신규 컬럼(시작 유닉스타임) 생성 후 종료유닉스 타임 값 입력, 종료 유닉스 타임 컬럼 제거\n",
+ " move = move.rename(columns = {'end_unix':'start_unix'})\n",
+ " # 5. 이동류 이력정보 READ\n",
+ " # - CSV 파일로 서버에 저장된 이동류정보를 읽어옴(파일이 없는 경우에는 데이터가 없는 프레임 D 생성)\n",
+ " try:\n",
+ " if isinstance(movement, pd.DataFrame): # movement가 존재할 경우 그걸 그대로 씀.\n",
+ " pass\n",
+ " else: \n",
+ " movement = pd.DataFrame()\n",
+ " except NameError: # movement가 존재하지 않는 경우 생성\n",
+ " movement = pd.DataFrame()\n",
+ " # 6. 이동류 이력정보 데이터테이블(D)에 C데이터 add\n",
+ " movement = pd.concat([movement, move])\n",
+ " # 7. D데이터 프레임에서 중복데이터 제거(교차로번호, 시작 유닉스타임, A링 현시번호, B링 현시번호 같은 행은 제거)\n",
+ " movement = movement.drop_duplicates(['inter_no','phas_A','phas_B','start_unix'])\n",
+ " # 8. D데이터 보관 시간 기준시간을 시작 유닉스 타임의 최대값 - 3600을 값으로 산출하고, 보관 시간 기준시간보다 작은 시작 유닉스 타임을 가진 행은 모두 제거(1시간 데이터만 보관)\n",
+ " movement = movement[movement.start_unix > fsec - 3600]\n",
+ " movement = movement.sort_values(by=['start_unix','inter_no','phas_A','phas_B']).reset_index(drop=True)\n",
+ "\n",
+ " time2movement[fsec] = movement\n",
+ " movement.to_csv(f'../../Data/tables/movements/movements_{fsec}.csv')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# C. 5분 간격으로 신호이력 수집 및 통합테이블 생성"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "midnight = int(datetime(2024, 1, 5, 0, 0, 0).timestamp())\n",
+ "next_day = int(datetime(2024, 1, 6, 0, 0, 0).timestamp())\n",
+ "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 27,
+ "metadata": {},
+ "outputs": [],
"source": [
- "Rhists = make_rhistory(100)\n",
- "Rhists"
+ "def make_splits(plan):\n",
+ " # split, isplit : A,B 분리 혹은 통합시 사용될 수 있는 딕셔너리 \n",
+ " splits = {} # splits maps (inter_no, start_hour, start_minute) to split \n",
+ " for i, row in plan.iterrows():\n",
+ " inter_no = row.inter_no\n",
+ " start_hour = row.start_hour\n",
+ " start_minute = row.start_minute\n",
+ " cycle = row.cycle\n",
+ " cums_A = row[[f'dura_A{j}' for j in range(1,9)]].cumsum()\n",
+ " cums_B = row[[f'dura_B{j}' for j in range(1,9)]].cumsum()\n",
+ " splits[(inter_no, start_hour, start_minute)] = {} # split maps (phas_A, phas_B) to k\n",
+ " k = 0\n",
+ " for t in range(cycle):\n",
+ " new_phas_A = len(cums_A[cums_A < t]) + 1\n",
+ " new_phas_B = len(cums_B[cums_B < t]) + 1\n",
+ " if k == 0 or ((new_phas_A, new_phas_B) != (phas_A, phas_B)):\n",
+ " k += 1\n",
+ " phas_A = new_phas_A\n",
+ " phas_B = new_phas_B\n",
+ " splits[(inter_no, start_hour, start_minute)][(phas_A, phas_B)] = k\n",
+ "\n",
+ " isplits = {} # the inverse of splits\n",
+ " for i in splits:\n",
+ " isplits[i] = {splits[i][k]:k for k in splits[i]} # isplit maps k to (phas_A, phas_B)\n",
+ " return splits, isplits\n",
+ "\n",
+ "def make_timetable(plan):\n",
+ " # timetable\n",
+ " timetable = plan[['start_hour', 'start_minute']].drop_duplicates()\n",
+ " timetable['start_seconds'] = midnight + timetable['start_hour'] * 3600 + timetable['start_minute'] * 60\n",
+ " return timetable\n",
+ "\n",
+ "# inter2node\n",
+ "inter_node = pd.read_csv('../../Data/tables/inter_node.csv', index_col=0)\n",
+ "inter2node = dict(zip(inter_node['inter_no'], inter_node['node_id']))"
]
},
{
"cell_type": "code",
- "execution_count": 12,
+ "execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
- "def make_histid(m):\n",
- " fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
- " present_time = fmins[m]\n",
- " rhistory = make_rhistory(m)\n",
+ "def make_rhists(present_time, timetable, plan, history):\n",
+ " # 1. 조회시점의 유닉스 타임 이전의 신호이력 수집\n",
+ " rhistory = history.copy() # recent history\n",
+ " rhistory = rhistory[(rhistory.end_unix < present_time)]\n",
" # 2. 시작 유닉스 타임컬럼 생성 후 종류 유닉스 타임에서 현시별 현시기간 컬럼의 합을 뺀 값으로 입력\n",
" # - 현시시간의 합을 뺀 시간의 +- 10초 이내에 이전 주기정보가 존재하면 그 유닉스 시간을 시작 유닉스시간 값으로 하고, 존재하지 않으면 현시시간의 합을 뺀 유닉스 시간을 시작 유닉스 시간으로 지정\n",
" for i, row in rhistory.iterrows():\n",
- " # 이전 유닉스 존재하지 않음 => 현시시간 합의 차\n",
- " # 이전 유닉스 존재, abs < 10 => 이전 유닉스\n",
- " # 이전 유닉스 존재, abs >=10 => 현시시간 합의 차\n",
" inter_no = row.inter_no\n",
" end_unix = row.end_unix\n",
" elapsed_time = row[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]].sum() // 2 # 현시시간 합\n",
+ " # 이전 유닉스 존재하지 않음 : 현시시간 합의 차\n",
" start_unix = end_unix - elapsed_time\n",
" pre_rows = history[:i] # previous rows\n",
" if inter_no in pre_rows.inter_no.unique(): # 이전 유닉스 존재\n",
" pre_unix = pre_rows[pre_rows.inter_no == inter_no]['end_unix'].iloc[-1] # previous unix time\n",
- " if abs(pre_unix - start_unix) < 10: # abs < 10\n",
+ " # 이전 유닉스 존재, abs < 10 : 이전 유닉스\n",
+ " if abs(pre_unix - start_unix) < 10:\n",
" start_unix = pre_unix\n",
- " else: # abs >= 10\n",
+ " # 이전 유닉스 존재, abs >=10 : 현시시간 합의 차\n",
+ " else:\n",
" pass\n",
- " rhistory.loc[i, 'start_unix'] = start_unix\n",
+ " rhistory.loc[i, 'start_unix'] = start_unix \n",
" rhistory[rhistory.isna()] = 0\n",
" rhistory['start_unix'] = rhistory['start_unix'].astype(int)\n",
- " # # with pd.option_context('display.max_rows', None, 'display.max_columns', None):\n",
- " # # display(rhistory)\n",
+ " rhistory[['inter_no', 'start_unix', 'cycle']][rhistory.inter_no==175]\n",
" rhistory = rhistory[['inter_no', 'start_unix'] + [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)] + ['cycle']]\n",
"\n",
+ " # 2-1. 참값 판단 프로세스\n",
+ " hours = np.array(range(midnight, next_day + 1, 3600)) # 정각에 해당하는 시각들 목록\n",
+ "\n",
+ " def calculate_DS(rhist, curr_unix):\n",
+ " ghour_lt_curr_unix = hours[hours <= curr_unix].max() # the greatest hour less than (or equal to) curr_unix\n",
+ " start_unixes = rhist.start_unix.unique()\n",
+ " start_unixes_lt_ghour = np.sort(start_unixes[start_unixes < ghour_lt_curr_unix]) # start unixes less than ghour_lt_curr_unix\n",
+ " # 기준유닉스(base_unix) : curr_unix보다 작은 hour 중에서 가장 큰 값으로부터 다섯 번째로 작은 start_unix\n",
+ " if list(start_unixes_lt_ghour):\n",
+ " base_unix = start_unixes_lt_ghour[-5]\n",
+ " # start_unixes_lt_ghour가 비었을 경우에는 맨 앞 start_unix로 base_unix를 지정\n",
+ " else:\n",
+ " base_unix = rhist.start_unix.min()\n",
+ " D_n = curr_unix - base_unix\n",
+ " S_n_durs = rhist[(rhist.start_unix > base_unix) & (rhist.start_unix <= curr_unix)] \\\n",
+ " [[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]]\n",
+ " S_n = S_n_durs.values.sum() // 2\n",
+ " return D_n, S_n\n",
+ "\n",
+ " rhists = []\n",
+ " for inter_no in sorted(rhistory.inter_no.unique()):\n",
+ " rhist = rhistory.copy()[rhistory.inter_no==inter_no]\n",
+ " rhist = rhist.drop_duplicates(subset=['start_unix']).reset_index(drop=True)\n",
+ "\n",
+ " # D_n 및 S_n 값 정의\n",
+ " rhist['D_n'] = 0 # D_n : 시간차이\n",
+ " rhist['S_n'] = 0 # S_n : 현시시간합\n",
+ " for n in range(len(rhist)):\n",
+ " curr_unix = rhist.iloc[n].start_unix # current start_unix\n",
+ " rhist.loc[n, ['D_n', 'S_n']] = calculate_DS(rhist, curr_unix)\n",
+ "\n",
+ " # 이전시각, 현재시각\n",
+ " prev_unix = rhist.loc[0, 'start_unix'] # previous start_unix\n",
+ " curr_unix = rhist.loc[1, 'start_unix'] # current start_unix\n",
+ "\n",
+ " # rhist의 마지막 행에 도달할 때까지 반복\n",
+ " while True:\n",
+ " n = rhist[rhist.start_unix==curr_unix].index[0]\n",
+ " cycle = rhist.loc[n, 'cycle']\n",
+ " D_n = rhist.loc[n, 'D_n']\n",
+ " S_n = rhist.loc[n, 'S_n']\n",
+ " # 참값인 경우\n",
+ " if (abs(D_n - S_n) <= 5):\n",
+ " pass\n",
+ " # 참값이 아닌 경우\n",
+ " else:\n",
+ " # 2-1-1. 결측치 처리 : 인접한 두 start_unix의 차이가 계획된 주기의 두 배보다 크면 결측이 일어났다고 판단, 신호계획의 현시시간으로 \"대체\"\n",
+ " if curr_unix - prev_unix >= 2 * cycle:\n",
+ " # prev_unix를 계획된 주기만큼 늘려가면서 한 행씩 채워나간다.\n",
+ " # (curr_unix와의 차이가 계획된 주기보다 작거나 같아질 때까지)\n",
+ " new_rows = []\n",
+ " while curr_unix - prev_unix > cycle:\n",
+ " prev_unix += cycle\n",
+ " # 신호 계획(prow) 불러오기\n",
+ " start_seconds = np.array(timetable.start_seconds)\n",
+ " idx = (start_seconds <= prev_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[idx].start_hour\n",
+ " start_minute = timetable.iloc[idx].start_minute\n",
+ " prow = plan.copy()[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
+ " # prow에서 필요한 부분을 rhist에 추가\n",
+ " prow['start_unix'] = prev_unix\n",
+ " prow = prow.drop(['start_hour', 'start_minute', 'offset'], axis=1)\n",
+ " cycle = prow.iloc[0].cycle\n",
+ " rhist = pd.concat([rhist, prow])\n",
+ " rhist = rhist.sort_values(by='start_unix').reset_index(drop=True)\n",
+ " n += 1\n",
+ "\n",
+ " # 2-1-2. 이상치 처리 : 비율에 따라 해당 행을 \"삭제\"(R_n <= 0.5) 또는 \"조정\"(R_n > 0.5)한다\n",
+ " R_n = (curr_unix - prev_unix) / cycle # R_n : 비율\n",
+ " # R_n이 0.5보다 작거나 같으면 해당 행을 삭제\n",
+ " if R_n <= 0.5:\n",
+ " rhist = rhist.drop(index=n).reset_index(drop=True)\n",
+ " # 행삭제에 따른 curr_unix, R_n 재정의\n",
+ " curr_unix = rhist.loc[n, 'start_unix']\n",
+ " R_n = (curr_unix - prev_unix) / cycle # R_n : 비율\n",
+ "\n",
+ " # R_n이 0.5보다 크면 해당 행 조정 (비율을 유지한 채로 현시시간 대체)\n",
+ " if R_n > 0.5:\n",
+ " # 신호 계획(prow) 불러오기\n",
+ " start_seconds = np.array(timetable.start_seconds)\n",
+ " idx = (start_seconds <= curr_unix).sum() - 1\n",
+ " start_hour = timetable.iloc[idx].start_hour\n",
+ " start_minute = timetable.iloc[idx].start_minute\n",
+ " prow = plan[(plan.inter_no==inter_no) & (plan.start_hour==start_hour) & (plan.start_minute==start_minute)] # planned row\n",
+ " # 조정된 현시시간 (prow에 R_n을 곱하고 정수로 바꿈)\n",
+ " adjusted_dur = prow.copy()[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] * R_n\n",
+ " int_parts = adjusted_dur.iloc[0].apply(lambda x: int(x))\n",
+ " frac_parts = adjusted_dur.iloc[0] - int_parts\n",
+ " difference = round(adjusted_dur.iloc[0].sum()) - int_parts.sum()\n",
+ " for _ in range(difference): # 소수 부분이 가장 큰 상위 'difference'개의 값에 대해 올림 처리\n",
+ " max_frac_index = frac_parts.idxmax()\n",
+ " int_parts[max_frac_index] += 1\n",
+ " frac_parts[max_frac_index] = 0 # 이미 처리된 항목은 0으로 설정\n",
+ " # rhist에 조정된 현시시간을 반영\n",
+ " rhist.loc[n, [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]] = int_parts.values\n",
+ " rhist.loc[n, 'cycle'] = int_parts.sum().sum() // 2\n",
+ "\n",
+ " if n == rhist.index[-1]:\n",
+ " break\n",
+ " prev_unix = curr_unix\n",
+ " curr_unix = rhist.loc[n+1, 'start_unix']\n",
+ "\n",
+ " # 생략해도 무방할 코드\n",
+ " rhist = rhist.reset_index(drop=True)\n",
+ " rhist = rhist.sort_values(by=['start_unix'])\n",
+ "\n",
+ " # D_n 및 S_n 값 재정의\n",
+ " for n in range(len(rhist)):\n",
+ " curr_unix = rhist.iloc[n].start_unix # current start_unix\n",
+ " rhist.loc[n, ['D_n', 'S_n']] = calculate_DS(rhist, curr_unix)\n",
+ " rhists.append(rhist)\n",
+ " rhists = pd.concat(rhists).sort_values(by=['start_unix','inter_no'])\n",
+ " rhists = rhists[rhists.start_unix >= present_time - 3600]\n",
+ " rhists = rhists.drop(columns=['D_n', 'S_n'])\n",
+ " return rhists"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_hrhists(rhists, isplits, timetable):\n",
" # 계층화된 형태로 변환\n",
- " hrhistory = [] # hierarchied recent history\n",
- " for i, row in rhistory.iterrows():\n",
+ " hrhists = [] # hierarchied recent history\n",
+ " for i, row in rhists.iterrows():\n",
" inter_no = row.inter_no\n",
" start_unix = row.start_unix\n",
"\n",
@@ -8023,15 +796,66 @@
" durations.append(abs(durs_A[ja-1] - durs_B[ja-1]))\n",
" new_rows = pd.DataFrame({'inter_no':[inter_no] * len(durations), 'start_unix':[start_unix] * len(durations),\n",
" 'phas_A':phas_As, 'phas_B':phas_Bs, 'duration':durations})\n",
- " hrhistory.append(new_rows)\n",
- " hrhistory = pd.concat(hrhistory)\n",
- " hrhistory = hrhistory.sort_values(by = ['start_unix', 'inter_no', 'phas_A', 'phas_B']).reset_index(drop=True)\n",
+ " hrhists.append(new_rows)\n",
+ " hrhists = pd.concat(hrhists)\n",
+ " hrhists = hrhists.sort_values(by = ['start_unix', 'inter_no', 'phas_A', 'phas_B']).reset_index(drop=True)\n",
+ " return hrhists"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_movements():\n",
+ " movements_path = '../../Data/tables/movements/'\n",
+ " movements_list = [pd.read_csv(movements_path + file, index_col=0) for file in tqdm(os.listdir(movements_path))]\n",
+ " movements = pd.concat(movements_list)\n",
+ " movements = movements.drop(columns=['start_unix'])\n",
+ " movements = movements.drop_duplicates()\n",
+ " movements = movements.sort_values(by=['inter_no', 'phas_A', 'phas_B'])\n",
+ " movements = movements.reset_index(drop=True)\n",
+ " movements.to_csv(movements_path + 'movements.csv')\n",
+ " return movements"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def update_movement(hrhists, movement, movements):\n",
+ " # 중복을 제거하고 (inter_no, start_unix) 쌍을 만듭니다.\n",
+ " hrhists_inter_unix = set(hrhists[['inter_no', 'start_unix']].drop_duplicates().itertuples(index=False, name=None))\n",
+ " movement_inter_unix = set(movement[['inter_no', 'start_unix']].drop_duplicates().itertuples(index=False, name=None))\n",
"\n",
- " # 5초단위로 수집한 이동류정보(time2movement[present_time])와 최근 1시간 신호이력(hrhistory)을 병합\n",
- " movedur = pd.merge(time2movement[present_time], hrhistory, how='inner', on=['inter_no', 'start_unix', 'phas_A', 'phas_B']) # movements and durations\n",
- " movedur = movedur.sort_values(by=['start_unix', 'inter_no', 'phas_A','phas_B'])\n",
- " movedur = movedur[['inter_no', 'start_unix', 'phas_A', 'phas_B', 'move_A', 'move_B', 'duration']]\n",
+ " # hrhists에는 있지만 movement에는 없는 (inter_no, start_unix) 쌍을 찾습니다.\n",
+ " missing_in_movement = hrhists_inter_unix - movement_inter_unix\n",
"\n",
+ " # 새로운 행들을 생성합니다.\n",
+ " new_rows = []\n",
+ " for inter_no, start_unix in missing_in_movement:\n",
+ " # movements에서 해당 inter_no의 데이터를 찾습니다.\n",
+ " new_row = movements[movements['inter_no'] == inter_no].copy()\n",
+ " # start_unix 값을 설정합니다.\n",
+ " new_row['start_unix'] = start_unix\n",
+ " new_rows.append(new_row)\n",
+ "\n",
+ " # 새로운 데이터프레임을 생성하고 기존 movement 데이터프레임과 합칩니다.\n",
+ " new_movement = pd.concat(new_rows, ignore_index=True)\n",
+ " movement_updated = pd.concat([movement, new_movement], ignore_index=True)\n",
+ " return movement_updated"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def make_histid(present_time, movedur):\n",
" # 이동류 매칭 테이블에서 진입id, 진출id를 가져와서 붙임.\n",
" for i, row in movedur.iterrows():\n",
" inter_no = row.inter_no\n",
@@ -8064,168 +888,328 @@
" histid['node_id'] = histid['inter_no'].map(inter2node)\n",
" histid = histid[['inter_no', 'node_id', 'start_unix', 'phas_A', 'phas_B', 'duration', 'inc_edge_A', 'out_edge_A', 'inc_edge_B', 'out_edge_B']]\n",
" histid = histid[histid.start_unix > present_time - 3600]\n",
- " # 시뮬레이션 시작시각 : 현재시각 - 600\n",
- " # 시뮬레이션 종료시각 : 현재시각 - 300\n",
- " # 현재시각 : present_time, PT\n",
- " # PT-900 ... PT-600 ... PT-300 ... PT\n",
" return histid"
]
},
{
"cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "m = 120\n",
- "fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
- "present_time = fmins[m]\n",
- "rhistory = make_rhistory(m)\n",
- "# 2. 시작 유닉스 타임컬럼 생성 후 종류 유닉스 타임에서 현시별 현시기간 컬럼의 합을 뺀 값으로 입력\n",
- "# - 현시시간의 합을 뺀 시간의 +- 10초 이내에 이전 주기정보가 존재하면 그 유닉스 시간을 시작 유닉스시간 값으로 하고, 존재하지 않으면 현시시간의 합을 뺀 유닉스 시간을 시작 유닉스 시간으로 지정\n",
- "for i, row in rhistory.iterrows():\n",
- " # 이전 유닉스 존재하지 않음 => 현시시간 합의 차\n",
- " # 이전 유닉스 존재, abs < 10 => 이전 유닉스\n",
- " # 이전 유닉스 존재, abs >=10 => 현시시간 합의 차\n",
- " inter_no = row.inter_no\n",
- " end_unix = row.end_unix\n",
- " elapsed_time = row[[f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)]].sum() // 2 # 현시시간 합\n",
- " start_unix = end_unix - elapsed_time\n",
- " pre_rows = history[:i] # previous rows\n",
- " if inter_no in pre_rows.inter_no.unique(): # 이전 유닉스 존재\n",
- " pre_unix = pre_rows[pre_rows.inter_no == inter_no]['end_unix'].iloc[-1] # previous unix time\n",
- " if abs(pre_unix - start_unix) < 10: # abs < 10\n",
- " start_unix = pre_unix\n",
- " else: # abs >= 10\n",
- " pass\n",
- " rhistory.loc[i, 'start_unix'] = start_unix\n",
- "rhistory[rhistory.isna()] = 0\n",
- "rhistory['start_unix'] = rhistory['start_unix'].astype(int)\n",
- "# # with pd.option_context('display.max_rows', None, 'display.max_columns', None):\n",
- "# # display(rhistory)\n",
- "rhistory = rhistory[['inter_no', 'start_unix'] + [f'dura_{alph}{j}' for alph in ['A', 'B'] for j in range(1,9)] + ['cycle']]\n",
- "\n",
- "# rhistoryy = rhistory.copy()[rhistory.inter_no==175]\n",
- "# rhistoryy['diff'] = rhistoryy['start_unix'].diff()\n",
- "\n",
- "# 계층화된 형태로 변환\n",
- "hrhistory = [] # hierarchied recent history\n",
- "for i, row in rhistory.iterrows():\n",
- " inter_no = row.inter_no\n",
- " start_unix = row.start_unix\n",
- "\n",
- " ind = (timetable['start_seconds'] <= row.start_unix).sum() - 1\n",
- " start_hour = timetable.iloc[ind].start_hour\n",
- " start_minute = timetable.iloc[ind].start_minute\n",
- " isplit = isplits[(inter_no, start_hour, start_minute)]\n",
- " phas_As = [isplit[j][0] for j in isplit.keys()]\n",
- " phas_Bs = [isplit[j][1] for j in isplit.keys()]\n",
- " durs_A = row[[f'dura_A{j}' for j in range(1,9)]]\n",
- " durs_B = row[[f'dura_B{j}' for j in range(1,9)]]\n",
- " durations = []\n",
- " for j in range(1, len(isplit)+1):\n",
- " ja = isplit[j][0]\n",
- " jb = isplit[j][1]\n",
- " if ja == jb:\n",
- " durations.append(min(durs_A[ja-1], durs_B[jb-1]))\n",
- " else:\n",
- " durations.append(abs(durs_A[ja-1] - durs_B[ja-1]))\n",
- " new_rows = pd.DataFrame({'inter_no':[inter_no] * len(durations), 'start_unix':[start_unix] * len(durations),\n",
- " 'phas_A':phas_As, 'phas_B':phas_Bs, 'duration':durations})\n",
- " hrhistory.append(new_rows)\n",
- "hrhistory = pd.concat(hrhistory)\n",
- "hrhistory = hrhistory.sort_values(by = ['start_unix', 'inter_no', 'phas_A', 'phas_B']).reset_index(drop=True)\n",
- "\n",
- "hrhistoryy = rhistory.copy()[rhistory.inter_no==175]\n",
- "hrhistoryy['diff'] = hrhistoryy['start_unix'].diff()\n",
- "\n",
- "# display(hrhistoryy[:60])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "for inter_no in sorted(plan.inter_no.unique()):\n",
- " print(inter_no)\n",
- " movement = time2movement[present_time]\n",
- " movementt = movement.copy()[movement.inter_no==inter_no]\n",
- " hrhistoryy = rhistory.copy()[rhistory.inter_no==inter_no]\n",
- " mdts = sorted(movementt.start_unix.unique())\n",
- " hdts = sorted(hrhistoryy.start_unix.unique())\n",
- " import matplotlib.pyplot as plt\n",
- " plt.scatter(mdts, [0]*len(mdts), c='b')\n",
- " plt.scatter(hdts, [1]*len(hdts), c='r')\n",
- " plt.show()\n",
- " # display(movementt)\n",
- " # display(hrhistoryy)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
+ "execution_count": 44,
"metadata": {},
"outputs": [],
"source": [
- "# 5초단위로 수집한 이동류정보(time2movement[present_time])와 최근 1시간 신호이력(hrhistory)을 병합\n",
- "movedur = pd.merge(time2movement[present_time], hrhistory, how='inner', on=['inter_no', 'start_unix', 'phas_A', 'phas_B']) # movements and durations\n",
- "movedur = movedur.sort_values(by=['start_unix', 'inter_no', 'phas_A','phas_B'])\n",
- "movedur = movedur[['inter_no', 'start_unix', 'phas_A', 'phas_B', 'move_A', 'move_B', 'duration']]\n",
- "\n",
- "# 이동류 매칭 테이블에서 진입id, 진출id를 가져와서 붙임.\n",
- "for i, row in movedur.iterrows():\n",
- " inter_no = row.inter_no\n",
- " start_unix = row.start_unix\n",
- " # incoming and outgoing edges A\n",
- " move_A = row.move_A\n",
- " if move_A in [17, 18]:\n",
- " inc_edge_A = np.nan\n",
- " out_edge_A = np.nan\n",
- " else:\n",
- " match_A = matching[(matching.inter_no == inter_no) & (matching.move_no == move_A)].iloc[0]\n",
- " inc_edge_A = match_A.inc_edge\n",
- " out_edge_A = match_A.out_edge\n",
- " movedur.loc[i, ['inc_edge_A', 'out_edge_A']] = [inc_edge_A, out_edge_A]\n",
- " # incoming and outgoing edges B\n",
- " move_B = row.move_B\n",
- " if move_B in [17, 18]:\n",
- " inc_edge_B = np.nan\n",
- " out_edge_B = np.nan\n",
- " else:\n",
- " match_B = matching[(matching.inter_no == inter_no) & (matching.move_no == move_B)].iloc[0]\n",
- " inc_edge_B = match_B.inc_edge\n",
- " out_edge_B = match_B.out_edge\n",
- " movedur.loc[i, ['inc_edge_B', 'out_edge_B']] = [inc_edge_B, out_edge_B]\n",
- "\n",
- "# 이동류 컬럼 제거\n",
- "movedur = movedur.drop(['move_A', 'move_B'], axis=1)\n",
- "\n",
- "histid = movedur.copy() # history with edge ids (incoming and outgoing edge ids)\n",
- "histid['node_id'] = histid['inter_no'].map(inter2node)\n",
- "histid = histid[['inter_no', 'node_id', 'start_unix', 'phas_A', 'phas_B', 'duration', 'inc_edge_A', 'out_edge_A', 'inc_edge_B', 'out_edge_B']]\n",
- "histid = histid[histid.start_unix > present_time - 3600]\n",
- "# 시뮬레이션 시작시각 : 현재시각 - 600\n",
- "# 시뮬레이션 종료시각 : 현재시각 - 300\n",
- "# 현재시각 : present_time, PT\n",
- "# PT-900 ... PT-600 ... PT-300 ... PT\n",
- "\n",
- "histidd = histid.copy()[histid.inter_no==175]\n",
- "histidd['diff'] = histidd['start_unix'].diff()\n",
- "histidd[:60]"
+ "def histid_main(m):\n",
+ " '''\n",
+ " 통합테이블(histid)를 만드는 함수\n",
+ "\n",
+ " input : m\n",
+ " - m ranges from 0 to 287, but 0 makes an error where 288 = 86400//300\n",
+ " - present_time = fmins[m] : 현재시점\n",
+ "\n",
+ " output : histid (통합테이블, HISTory with edge_IDs)\n",
+ " - 컬럼 : inter_no, node_id, start_unix, phas_A, phas_B, duration, inc_edge_A, out_edge_A, inc_edge_B, out_edge_B\n",
+ "\n",
+ " 주요 데이터, 중간산출물 및 결과물 :\n",
+ " # 데이터\n",
+ " - history : 신호이력 (inter_no, end_unix, dura_Aj, dura_Bj, cycle, offset)\n",
+ " - plan : 신호계획 (inter_no, start_hour, start_minute, dura_Aj, dura_Bj cycle, offset)\n",
+ " # 중간산출물\n",
+ " - rhists (recent history)\n",
+ " - history에서 현재 시각 이전의 데이터를 가져옴.\n",
+ " - end_unix를 start_unix로 변환\n",
+ " - 참값판단 프로세스(결측·이상치 처리)\n",
+ " - 컬럼 : inter_no, start_unix, dura_Aj, dura_Bj, cycle\n",
+ " - hrhists (hierarchized recent history)\n",
+ " - rhists를 계층화\n",
+ " - 컬럼 : inter_no, start_unix, phas_A, phas_B, duration\n",
+ " - movements\n",
+ " - 각 교차로에 대하여 현시별로 이동류를 정해놓음.\n",
+ " - join시 사용하기 위함.\n",
+ " - 한 번 만들어놓고 두고두고 사용함.\n",
+ " - 컬럼 : inter_no, phas_A, phas_B, move_A, move_B\n",
+ " - movement\n",
+ " - 현재 시점에서의 이동류정보\n",
+ " - 컬럼 : inter_no, phas_A, phas_B, move_A, move_B, start_unix\n",
+ " - movement_updated\n",
+ " - movement와 hrhists를 join하기 전에, movement에는 없지만 hrhists에는 있는 start_unix에 대한 이동류 정보를 가져와 movement에 붙임\n",
+ " - 이동류정보는 앞서 정의한 movements에서 가져옴.\n",
+ " - 컬럼 : inter_no, phas_A, phas_B, move_A, move_B, start_unix\n",
+ " - movedur\n",
+ " - hrhists와 movement_updated를 join\n",
+ " - 컬럼 : inter_no, phas_A, phas_B, move_A, move_B, start_unix, duration\n",
+ " # 결과\n",
+ "\n",
+ " '''\n",
+ " midnight = int(datetime(2024, 1, 5, 0, 0, 0).timestamp())\n",
+ " next_day = int(datetime(2024, 1, 6, 0, 0, 0).timestamp())\n",
+ " fmins = range(midnight, next_day, 300) # fmins : unix time by Five MINuteS\n",
+ "\n",
+ " # 사용할 표준 테이블 목록\n",
+ " plan = pd.read_csv('../../Data/tables/plan.csv', index_col=0)\n",
+ " history = pd.read_csv('../../Data/tables/history.csv', index_col=0)\n",
+ "\n",
+ " # 참고할 딕셔너리, 데이터프레임 등 목록\n",
+ " splits, isplits = make_splits(plan)\n",
+ " timetable = make_timetable(plan)\n",
+ "\n",
+ " # 현재시점\n",
+ " present_time = fmins[m]\n",
+ " print(datetime.fromtimestamp(present_time))\n",
+ "\n",
+ " # rhists, hrhists\n",
+ " rhists = make_rhists(present_time, timetable, plan, history)\n",
+ " hrhists = make_hrhists(rhists, isplits, timetable)\n",
+ "\n",
+ " # movements, movement, movement_updated\n",
+ " movements = pd.read_csv('../../data/tables/movements/movements.csv', index_col=0)\n",
+ " movement = pd.read_csv(f'../../Data/tables/movements/movements_{present_time}.csv', index_col=0)\n",
+ " movement_updated = update_movement(hrhists, movement, movements)\n",
+ "\n",
+ " # movedur\n",
+ " movedur = pd.merge(movement_updated, hrhists, how='inner', on=['inter_no', 'start_unix', 'phas_A', 'phas_B']) # movements and durations\n",
+ " movedur = movedur.sort_values(by=['start_unix', 'inter_no', 'phas_A','phas_B'])\n",
+ " movedur = movedur[['inter_no', 'start_unix', 'phas_A', 'phas_B', 'move_A', 'move_B', 'duration']]\n",
+ "\n",
+ " # histid\n",
+ " histid = make_histid(present_time, movedur)\n",
+ "\n",
+ " \n",
+ " # hrhists['start_dt'] = hrhists['start_unix'].map(lambda x:datetime.fromtimestamp(x))\n",
+ "\n",
+ " return histid"
]
},
{
"cell_type": "code",
- "execution_count": 18,
+ "execution_count": 45,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "2024-01-05 08:20:00\n"
+ "2024-01-05 02:30:00\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " inter_no | \n",
+ " node_id | \n",
+ " start_unix | \n",
+ " phas_A | \n",
+ " phas_B | \n",
+ " duration | \n",
+ " inc_edge_A | \n",
+ " out_edge_A | \n",
+ " inc_edge_B | \n",
+ " out_edge_B | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 | \n",
+ " 175 | \n",
+ " u00 | \n",
+ " 1704385840 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 37 | \n",
+ " -571542797_02 | \n",
+ " 571500487_01 | \n",
+ " -571500487_01 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 1 | \n",
+ " 175 | \n",
+ " u00 | \n",
+ " 1704385840 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 39 | \n",
+ " -571500487_01 | \n",
+ " 571545870_01 | \n",
+ " -571542797_02 | \n",
+ " 571510153_01 | \n",
+ "
\n",
+ " \n",
+ " 2 | \n",
+ " 175 | \n",
+ " u00 | \n",
+ " 1704385840 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 25 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571545870_02 | \n",
+ " 571542797_02 | \n",
+ "
\n",
+ " \n",
+ " 3 | \n",
+ " 175 | \n",
+ " u00 | \n",
+ " 1704385840 | \n",
+ " 3 | \n",
+ " 4 | \n",
+ " 30 | \n",
+ " 571545870_02 | \n",
+ " 571510153_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " 4 | \n",
+ " 175 | \n",
+ " u00 | \n",
+ " 1704385840 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 29 | \n",
+ " 571510153_02 | \n",
+ " 571500487_01 | \n",
+ " 571510153_02 | \n",
+ " 571545870_01 | \n",
+ "
\n",
+ " \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ "
\n",
+ " \n",
+ " 764 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704389220 | \n",
+ " 3 | \n",
+ " 3 | \n",
+ " 17 | \n",
+ " 571500617_02 | \n",
+ " 571500618_01 | \n",
+ " 571500618_02 | \n",
+ " 571500617_01 | \n",
+ "
\n",
+ " \n",
+ " 765 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704389220 | \n",
+ " 4 | \n",
+ " 4 | \n",
+ " 58 | \n",
+ " 571500617_02 | \n",
+ " 571500618_01 | \n",
+ " 571500617_02 | \n",
+ " 571500569_01 | \n",
+ "
\n",
+ " \n",
+ " 766 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704389220 | \n",
+ " 5 | \n",
+ " 5 | \n",
+ " 17 | \n",
+ " 571500583_01 | \n",
+ " 571500617_01 | \n",
+ " 571500583_01 | \n",
+ " 571500569_01 | \n",
+ "
\n",
+ " \n",
+ " 767 | \n",
+ " 202 | \n",
+ " i9 | \n",
+ " 1704389220 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 39 | \n",
+ " 571510152_02 | \n",
+ " -571510152_01 | \n",
+ " 571510152_01 | \n",
+ " 571510152_01.65 | \n",
+ "
\n",
+ " \n",
+ " 768 | \n",
+ " 202 | \n",
+ " i9 | \n",
+ " 1704389220 | \n",
+ " 2 | \n",
+ " 2 | \n",
+ " 101 | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ " NaN | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
769 rows × 10 columns
\n",
+ "
"
+ ],
+ "text/plain": [
+ " inter_no node_id start_unix phas_A phas_B duration inc_edge_A \\\n",
+ "0 175 u00 1704385840 1 1 37 -571542797_02 \n",
+ "1 175 u00 1704385840 2 2 39 -571500487_01 \n",
+ "2 175 u00 1704385840 3 3 25 571545870_02 \n",
+ "3 175 u00 1704385840 3 4 30 571545870_02 \n",
+ "4 175 u00 1704385840 4 4 29 571510153_02 \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "764 201 i8 1704389220 3 3 17 571500617_02 \n",
+ "765 201 i8 1704389220 4 4 58 571500617_02 \n",
+ "766 201 i8 1704389220 5 5 17 571500583_01 \n",
+ "767 202 i9 1704389220 1 1 39 571510152_02 \n",
+ "768 202 i9 1704389220 2 2 101 NaN \n",
+ "\n",
+ " out_edge_A inc_edge_B out_edge_B \n",
+ "0 571500487_01 -571500487_01 571542797_02 \n",
+ "1 571545870_01 -571542797_02 571510153_01 \n",
+ "2 571510153_01 571545870_02 571542797_02 \n",
+ "3 571510153_01 571510153_02 571545870_01 \n",
+ "4 571500487_01 571510153_02 571545870_01 \n",
+ ".. ... ... ... \n",
+ "764 571500618_01 571500618_02 571500617_01 \n",
+ "765 571500618_01 571500617_02 571500569_01 \n",
+ "766 571500617_01 571500583_01 571500569_01 \n",
+ "767 -571510152_01 571510152_01 571510152_01.65 \n",
+ "768 NaN NaN NaN \n",
+ "\n",
+ "[769 rows x 10 columns]"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "2024-01-05 02:35:00\n"
]
},
{
@@ -8264,508 +1248,190 @@
" \n",
" \n",
" 0 | \n",
- " 177 | \n",
- " i2 | \n",
- " 1704406830 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704386139 | \n",
" 1 | \n",
" 1 | \n",
- " 40 | \n",
- " -571542809_01 | \n",
- " 571542811_01 | \n",
- " 571542811_02 | \n",
- " 571542809_01 | \n",
+ " 24 | \n",
+ " -571500569_01 | \n",
+ " 571500583_02 | \n",
+ " -571500569_01 | \n",
+ " 571500618_01 | \n",
"
\n",
" \n",
" 1 | \n",
- " 177 | \n",
- " i2 | \n",
- " 1704406830 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704386139 | \n",
" 2 | \n",
" 2 | \n",
- " 25 | \n",
- " 571542811_02 | \n",
- " 571542107_01 | \n",
- " -571542809_01 | \n",
- " 571542809_01 | \n",
+ " 24 | \n",
+ " 571500618_02 | \n",
+ " 571500583_02 | \n",
+ " 571500618_02 | \n",
+ " 571500617_01 | \n",
"
\n",
" \n",
" 2 | \n",
- " 177 | \n",
- " i2 | \n",
- " 1704406830 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704386139 | \n",
" 3 | \n",
" 3 | \n",
- " 71 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
+ " 17 | \n",
+ " 571500617_02 | \n",
+ " 571500618_01 | \n",
+ " 571500618_02 | \n",
+ " 571500617_01 | \n",
"
\n",
" \n",
" 3 | \n",
- " 177 | \n",
- " i2 | \n",
- " 1704406830 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704386139 | \n",
" 4 | \n",
" 4 | \n",
- " 34 | \n",
- " -571542809_01 | \n",
- " 571542811_01 | \n",
- " 571542107_02 | \n",
- " 571542809_01 | \n",
+ " 58 | \n",
+ " 571500617_02 | \n",
+ " 571500618_01 | \n",
+ " 571500617_02 | \n",
+ " 571500569_01 | \n",
"
\n",
" \n",
" 4 | \n",
- " 175 | \n",
- " i0 | \n",
- " 1704406870 | \n",
- " 1 | \n",
- " 1 | \n",
- " 40 | \n",
- " -571542797_02 | \n",
- " 571500487_01 | \n",
- " -571500487_01 | \n",
- " 571542797_02 | \n",
- "
\n",
- " \n",
- " 5 | \n",
- " 175 | \n",
- " i0 | \n",
- " 1704406870 | \n",
- " 2 | \n",
- " 2 | \n",
- " 42 | \n",
- " -571500487_01 | \n",
- " 571545870_01 | \n",
- " -571542797_02 | \n",
- " 571510153_01 | \n",
- "
\n",
- " \n",
- " 6 | \n",
- " 175 | \n",
- " i0 | \n",
- " 1704406870 | \n",
- " 3 | \n",
- " 3 | \n",
- " 29 | \n",
- " 571545870_02 | \n",
- " 571510153_01 | \n",
- " 571545870_02 | \n",
- " 571542797_02 | \n",
+ " 201 | \n",
+ " i8 | \n",
+ " 1704386139 | \n",
+ " 5 | \n",
+ " 5 | \n",
+ " 17 | \n",
+ " 571500583_01 | \n",
+ " 571500617_01 | \n",
+ " 571500583_01 | \n",
+ " 571500569_01 | \n",
"
\n",
" \n",
- " 7 | \n",
- " 175 | \n",
- " i0 | \n",
- " 1704406870 | \n",
- " 3 | \n",
- " 4 | \n",
- " 26 | \n",
- " 571545870_02 | \n",
- " 571510153_01 | \n",
- " 571510153_02 | \n",
- " 571545870_01 | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
+ " ... | \n",
"
\n",
" \n",
- " 8 | \n",
+ " 768 | \n",
" 175 | \n",
- " i0 | \n",
- " 1704406870 | \n",
+ " u00 | \n",
+ " 1704389520 | \n",
" 4 | \n",
" 4 | \n",
- " 33 | \n",
+ " 29 | \n",
" 571510153_02 | \n",
" 571500487_01 | \n",
" 571510153_02 | \n",
" 571545870_01 | \n",
"
\n",
" \n",
- " 9 | \n",
- " 176 | \n",
- " i1 | \n",
- " 1704406910 | \n",
- " 1 | \n",
- " 1 | \n",
- " 37 | \n",
- " -571542810_01 | \n",
- " -571542797_02.99 | \n",
- " 571542797_02.99 | \n",
- " 571542810_01 | \n",
- "
\n",
- " \n",
- " 10 | \n",
- " 176 | \n",
- " i1 | \n",
- " 1704406910 | \n",
- " 2 | \n",
- " 2 | \n",
- " 93 | \n",
- " -571542810_01 | \n",
- " -571542797_02.99 | \n",
- " -571542810_01 | \n",
- " 571543469_01 | \n",
- "
\n",
- " \n",
- " 11 | \n",
- " 176 | \n",
- " i1 | \n",
- " 1704406910 | \n",
- " 3 | \n",
- " 3 | \n",
- " 40 | \n",
- " 571543469_02 | \n",
- " -571542797_02.99 | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 12 | \n",
- " 178 | \n",
- " i3 | \n",
- " 1704406950 | \n",
- " 1 | \n",
- " 1 | \n",
- " 38 | \n",
- " 571540304_02 | \n",
- " 571556450_01 | \n",
- " 571556450_02 | \n",
- " 571540304_01 | \n",
- "
\n",
- " \n",
- " 13 | \n",
- " 178 | \n",
- " i3 | \n",
- " 1704406950 | \n",
- " 2 | \n",
- " 2 | \n",
- " 39 | \n",
- " 571556450_02 | \n",
- " 571500475_01 | \n",
- " 571540304_02 | \n",
- " 571540303_01 | \n",
- "
\n",
- " \n",
- " 14 | \n",
- " 178 | \n",
- " i3 | \n",
- " 1704406950 | \n",
- " 3 | \n",
- " 3 | \n",
- " 42 | \n",
- " 571540303_02.21 | \n",
- " 571556450_01 | \n",
- " 571540303_02.21 | \n",
- " 571500475_01 | \n",
- "
\n",
- " \n",
- " 15 | \n",
- " 178 | \n",
- " i3 | \n",
- " 1704406950 | \n",
- " 4 | \n",
- " 4 | \n",
- " 21 | \n",
- " -571500475_01 | \n",
- " 571540303_01 | \n",
- " -571500475_01 | \n",
- " 571540304_01 | \n",
- "
\n",
- " \n",
- " 16 | \n",
- " 202 | \n",
- " i9 | \n",
- " 1704406950 | \n",
- " 1 | \n",
- " 1 | \n",
- " 46 | \n",
- " 571510152_02 | \n",
- " -571510152_01 | \n",
- " 571510152_01 | \n",
- " 571510152_01.65 | \n",
- "
\n",
- " \n",
- " 17 | \n",
- " 202 | \n",
- " i9 | \n",
- " 1704406950 | \n",
- " 2 | \n",
- " 2 | \n",
- " 114 | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- " NaN | \n",
- "
\n",
- " \n",
- " 18 | \n",
- " 177 | \n",
- " i2 | \n",
- " 1704407000 | \n",
+ " 769 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704389520 | \n",
" 1 | \n",
" 1 | \n",
- " 40 | \n",
- " -571542809_01 | \n",
- " 571542811_01 | \n",
- " 571542811_02 | \n",
- " 571542809_01 | \n",
+ " 33 | \n",
+ " -571511538_02 | \n",
+ " 571542073_02 | \n",
+ " 571542073_01 | \n",
+ " 571511538_02 | \n",
"
\n",
" \n",
- " 19 | \n",
- " 177 | \n",
- " i2 | \n",
- " 1704407000 | \n",
+ " 770 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704389520 | \n",
" 2 | \n",
" 2 | \n",
- " 25 | \n",
- " 571542811_02 | \n",
- " 571542107_01 | \n",
- " -571542809_01 | \n",
- " 571542809_01 | \n",
- "
\n",
- " \n",
- " 20 | \n",
- " 177 | \n",
- " i2 | \n",
- " 1704407000 | \n",
- " 3 | \n",
- " 3 | \n",
- " 71 | \n",
+ " 35 | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
" NaN | \n",
"
\n",
" \n",
- " 21 | \n",
- " 177 | \n",
- " i2 | \n",
- " 1704407000 | \n",
- " 4 | \n",
- " 4 | \n",
- " 34 | \n",
- " -571542809_01 | \n",
- " 571542811_01 | \n",
- " 571542107_02 | \n",
- " 571542809_01 | \n",
- "
\n",
- " \n",
- " 22 | \n",
- " 175 | \n",
- " i0 | \n",
- " 1704407040 | \n",
- " 1 | \n",
- " 1 | \n",
- " 40 | \n",
- " -571542797_02 | \n",
- " 571500487_01 | \n",
- " -571500487_01 | \n",
- " 571542797_02 | \n",
- "
\n",
- " \n",
- " 23 | \n",
- " 175 | \n",
- " i0 | \n",
- " 1704407040 | \n",
- " 2 | \n",
- " 2 | \n",
- " 42 | \n",
- " -571500487_01 | \n",
- " 571545870_01 | \n",
- " -571542797_02 | \n",
- " 571510153_01 | \n",
- "
\n",
- " \n",
- " 24 | \n",
- " 175 | \n",
- " i0 | \n",
- " 1704407040 | \n",
- " 3 | \n",
+ " 771 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704389520 | \n",
" 3 | \n",
- " 29 | \n",
- " 571545870_02 | \n",
- " 571510153_01 | \n",
- " 571545870_02 | \n",
- " 571542797_02 | \n",
- "
\n",
- " \n",
- " 25 | \n",
- " 175 | \n",
- " i0 | \n",
- " 1704407040 | \n",
" 3 | \n",
- " 4 | \n",
" 26 | \n",
- " 571545870_02 | \n",
- " 571510153_01 | \n",
- " 571510153_02 | \n",
- " 571545870_01 | \n",
+ " -571511538_02 | \n",
+ " 571542073_02 | \n",
+ " 571542073_01 | \n",
+ " 571511538_02 | \n",
"
\n",
" \n",
- " 26 | \n",
- " 175 | \n",
- " i0 | \n",
- " 1704407040 | \n",
+ " 772 | \n",
+ " 206 | \n",
+ " i7 | \n",
+ " 1704389520 | \n",
" 4 | \n",
" 4 | \n",
- " 33 | \n",
- " 571510153_02 | \n",
- " 571500487_01 | \n",
- " 571510153_02 | \n",
- " 571545870_01 | \n",
- "
\n",
- " \n",
- " 27 | \n",
- " 176 | \n",
- " i1 | \n",
- " 1704407080 | \n",
- " 1 | \n",
- " 1 | \n",
- " 37 | \n",
- " -571542810_01 | \n",
- " -571542797_02.99 | \n",
- " 571542797_02.99 | \n",
- " 571542810_01 | \n",
- "
\n",
- " \n",
- " 28 | \n",
- " 176 | \n",
- " i1 | \n",
- " 1704407080 | \n",
- " 2 | \n",
- " 2 | \n",
- " 93 | \n",
- " -571542810_01 | \n",
- " -571542797_02.99 | \n",
- " -571542810_01 | \n",
- " 571543469_01 | \n",
- "
\n",
- " \n",
- " 29 | \n",
- " 176 | \n",
- " i1 | \n",
- " 1704407080 | \n",
- " 3 | \n",
- " 3 | \n",
- " 40 | \n",
- " 571543469_02 | \n",
- " -571542797_02.99 | \n",
+ " 26 | \n",
+ " NaN | \n",
+ " NaN | \n",
" NaN | \n",
" NaN | \n",
"
\n",
" \n",
"\n",
+ "773 rows × 10 columns
\n",
""
],
"text/plain": [
- " inter_no node_id start_unix phas_A phas_B duration inc_edge_A \\\n",
- "0 177 i2 1704406830 1 1 40 -571542809_01 \n",
- "1 177 i2 1704406830 2 2 25 571542811_02 \n",
- "2 177 i2 1704406830 3 3 71 NaN \n",
- "3 177 i2 1704406830 4 4 34 -571542809_01 \n",
- "4 175 i0 1704406870 1 1 40 -571542797_02 \n",
- "5 175 i0 1704406870 2 2 42 -571500487_01 \n",
- "6 175 i0 1704406870 3 3 29 571545870_02 \n",
- "7 175 i0 1704406870 3 4 26 571545870_02 \n",
- "8 175 i0 1704406870 4 4 33 571510153_02 \n",
- "9 176 i1 1704406910 1 1 37 -571542810_01 \n",
- "10 176 i1 1704406910 2 2 93 -571542810_01 \n",
- "11 176 i1 1704406910 3 3 40 571543469_02 \n",
- "12 178 i3 1704406950 1 1 38 571540304_02 \n",
- "13 178 i3 1704406950 2 2 39 571556450_02 \n",
- "14 178 i3 1704406950 3 3 42 571540303_02.21 \n",
- "15 178 i3 1704406950 4 4 21 -571500475_01 \n",
- "16 202 i9 1704406950 1 1 46 571510152_02 \n",
- "17 202 i9 1704406950 2 2 114 NaN \n",
- "18 177 i2 1704407000 1 1 40 -571542809_01 \n",
- "19 177 i2 1704407000 2 2 25 571542811_02 \n",
- "20 177 i2 1704407000 3 3 71 NaN \n",
- "21 177 i2 1704407000 4 4 34 -571542809_01 \n",
- "22 175 i0 1704407040 1 1 40 -571542797_02 \n",
- "23 175 i0 1704407040 2 2 42 -571500487_01 \n",
- "24 175 i0 1704407040 3 3 29 571545870_02 \n",
- "25 175 i0 1704407040 3 4 26 571545870_02 \n",
- "26 175 i0 1704407040 4 4 33 571510153_02 \n",
- "27 176 i1 1704407080 1 1 37 -571542810_01 \n",
- "28 176 i1 1704407080 2 2 93 -571542810_01 \n",
- "29 176 i1 1704407080 3 3 40 571543469_02 \n",
- "\n",
- " out_edge_A inc_edge_B out_edge_B \n",
- "0 571542811_01 571542811_02 571542809_01 \n",
- "1 571542107_01 -571542809_01 571542809_01 \n",
- "2 NaN NaN NaN \n",
- "3 571542811_01 571542107_02 571542809_01 \n",
- "4 571500487_01 -571500487_01 571542797_02 \n",
- "5 571545870_01 -571542797_02 571510153_01 \n",
- "6 571510153_01 571545870_02 571542797_02 \n",
- "7 571510153_01 571510153_02 571545870_01 \n",
- "8 571500487_01 571510153_02 571545870_01 \n",
- "9 -571542797_02.99 571542797_02.99 571542810_01 \n",
- "10 -571542797_02.99 -571542810_01 571543469_01 \n",
- "11 -571542797_02.99 NaN NaN \n",
- "12 571556450_01 571556450_02 571540304_01 \n",
- "13 571500475_01 571540304_02 571540303_01 \n",
- "14 571556450_01 571540303_02.21 571500475_01 \n",
- "15 571540303_01 -571500475_01 571540304_01 \n",
- "16 -571510152_01 571510152_01 571510152_01.65 \n",
- "17 NaN NaN NaN \n",
- "18 571542811_01 571542811_02 571542809_01 \n",
- "19 571542107_01 -571542809_01 571542809_01 \n",
- "20 NaN NaN NaN \n",
- "21 571542811_01 571542107_02 571542809_01 \n",
- "22 571500487_01 -571500487_01 571542797_02 \n",
- "23 571545870_01 -571542797_02 571510153_01 \n",
- "24 571510153_01 571545870_02 571542797_02 \n",
- "25 571510153_01 571510153_02 571545870_01 \n",
- "26 571500487_01 571510153_02 571545870_01 \n",
- "27 -571542797_02.99 571542797_02.99 571542810_01 \n",
- "28 -571542797_02.99 -571542810_01 571543469_01 \n",
- "29 -571542797_02.99 NaN NaN "
+ " inter_no node_id start_unix phas_A phas_B duration inc_edge_A \\\n",
+ "0 201 i8 1704386139 1 1 24 -571500569_01 \n",
+ "1 201 i8 1704386139 2 2 24 571500618_02 \n",
+ "2 201 i8 1704386139 3 3 17 571500617_02 \n",
+ "3 201 i8 1704386139 4 4 58 571500617_02 \n",
+ "4 201 i8 1704386139 5 5 17 571500583_01 \n",
+ ".. ... ... ... ... ... ... ... \n",
+ "768 175 u00 1704389520 4 4 29 571510153_02 \n",
+ "769 206 i7 1704389520 1 1 33 -571511538_02 \n",
+ "770 206 i7 1704389520 2 2 35 NaN \n",
+ "771 206 i7 1704389520 3 3 26 -571511538_02 \n",
+ "772 206 i7 1704389520 4 4 26 NaN \n",
+ "\n",
+ " out_edge_A inc_edge_B out_edge_B \n",
+ "0 571500583_02 -571500569_01 571500618_01 \n",
+ "1 571500583_02 571500618_02 571500617_01 \n",
+ "2 571500618_01 571500618_02 571500617_01 \n",
+ "3 571500618_01 571500617_02 571500569_01 \n",
+ "4 571500617_01 571500583_01 571500569_01 \n",
+ ".. ... ... ... \n",
+ "768 571500487_01 571510153_02 571545870_01 \n",
+ "769 571542073_02 571542073_01 571511538_02 \n",
+ "770 NaN NaN NaN \n",
+ "771 571542073_02 571542073_01 571511538_02 \n",
+ "772 NaN NaN NaN \n",
+ "\n",
+ "[773 rows x 10 columns]"
]
},
- "execution_count": 18,
"metadata": {},
- "output_type": "execute_result"
+ "output_type": "display_data"
}
],
"source": [
- "make_histid(100)[:30]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "inter_no = 175\n",
- "rhist = make_histid(100)\n",
- "rhis = rhist.copy()[rhist.inter_no==inter_no]\n",
- "rhis['diff'] = rhis['start_unix'].diff()\n",
- "rhis[:60]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "inter_no = 175\n",
- "histid = make_histid(100)\n",
- "his = histid.copy()[histid.inter_no==inter_no]\n",
- "his['diff'] = his['start_unix'].diff()\n",
- "his[:60]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {},
- "outputs": [],
- "source": [
- "for m in range(30, 288):\n",
- " print(m)\n",
- " make_histid(m).to_csv(f'../../Data/tables/histids/histids_{fmins[m]}.csv')"
+ "for m in range(30, 32):\n",
+ " histid = histid_main(m)\n",
+ " display(histid)"
]
}
],
diff --git a/Data/tables/histids/histids_1704389400.csv b/Data/tables/histids/histids_1704389400.csv
index 149c0e6b2..d8f6f5577 100644
--- a/Data/tables/histids/histids_1704389400.csv
+++ b/Data/tables/histids/histids_1704389400.csv
@@ -1,145 +1,195 @@
-,inter_no,node_id,start_unix,phas_A,phas_B,duration,inc_edge_A,out_edge_A,inc_edge_B,out_edge_B
-467,178,i3,1704388520,1,1,38,571540304_02,571556450_01,571556450_02,571540304_01
-468,178,i3,1704388520,2,2,39,571556450_02,571500475_01,571540304_02,571540303_01
-469,178,i3,1704388520,3,3,40,571540303_02.21,571556450_01,571540303_02.21,571500475_01
-470,178,i3,1704388520,4,4,23,-571500475_01,571540303_01,-571500475_01,571540304_01
-471,201,i8,1704388520,1,1,24,-571500569_01,571500583_02,-571500569_01,571500618_01
-472,201,i8,1704388520,2,2,24,571500618_02,571500583_02,571500618_02,571500617_01
-473,201,i8,1704388520,3,3,17,571500617_02,571500618_01,571500618_02,571500617_01
-474,201,i8,1704388520,4,4,58,571500617_02,571500618_01,571500617_02,571500569_01
-475,201,i8,1704388520,5,5,17,571500583_01,571500617_01,571500583_01,571500569_01
-476,176,i1,1704388550,1,1,37,-571542810_01,-571542797_02.99,571542797_02.99,571542810_01
-477,176,i1,1704388550,2,2,73,-571542810_01,-571542797_02.99,-571542810_01,571543469_01
-478,176,i1,1704388550,3,3,40,571543469_02,-571542797_02.99,,
-479,175,i0,1704388560,1,1,37,-571542797_02,571500487_01,-571500487_01,571542797_02
-480,175,i0,1704388560,2,2,39,-571500487_01,571545870_01,-571542797_02,571510153_01
-481,175,i0,1704388560,3,3,25,571545870_02,571510153_01,571545870_02,571542797_02
-482,175,i0,1704388560,3,4,30,571545870_02,571510153_01,571510153_02,571545870_01
-483,175,i0,1704388560,4,4,29,571510153_02,571500487_01,571510153_02,571545870_01
-484,206,i7,1704388560,1,1,33,-571511538_02,571542073_02,571542073_01,571511538_02
-485,206,i7,1704388560,2,2,35,,,,
-486,206,i7,1704388560,3,3,26,-571511538_02,571542073_02,571542073_01,571511538_02
-487,206,i7,1704388560,4,4,26,,,,
-488,210,i6,1704388560,1,1,24,-571542115_01,571500535_01,,
-489,210,i6,1704388560,1,2,19,-571542115_01,571500535_01,571500535_02.18,571542115_01
-490,210,i6,1704388560,2,2,29,571500535_02.18,571511538_01,571500535_02.18,571542115_01
-491,210,i6,1704388560,3,3,56,571511538_02.121,571542115_01,571511538_02.121,571500585_01
-492,210,i6,1704388560,4,4,22,571500585_02,571511538_01,571500585_02,571500535_01
-493,178,i3,1704388660,1,1,38,571540304_02,571556450_01,571556450_02,571540304_01
-494,178,i3,1704388660,2,2,39,571556450_02,571500475_01,571540304_02,571540303_01
-495,178,i3,1704388660,3,3,40,571540303_02.21,571556450_01,571540303_02.21,571500475_01
-496,178,i3,1704388660,4,4,23,-571500475_01,571540303_01,-571500475_01,571540304_01
-497,201,i8,1704388660,1,1,24,-571500569_01,571500583_02,-571500569_01,571500618_01
-498,201,i8,1704388660,2,2,24,571500618_02,571500583_02,571500618_02,571500617_01
-499,201,i8,1704388660,3,3,17,571500617_02,571500618_01,571500618_02,571500617_01
-500,201,i8,1704388660,4,4,58,571500617_02,571500618_01,571500617_02,571500569_01
-501,201,i8,1704388660,5,5,17,571500583_01,571500617_01,571500583_01,571500569_01
-502,202,i9,1704388660,1,1,39,571510152_02,-571510152_01,571510152_01,571510152_01.65
-503,202,i9,1704388660,2,2,101,,,,
-504,206,i7,1704388680,1,1,33,-571511538_02,571542073_02,571542073_01,571511538_02
-505,206,i7,1704388680,2,2,35,,,,
-506,206,i7,1704388680,3,3,26,-571511538_02,571542073_02,571542073_01,571511538_02
-507,206,i7,1704388680,4,4,26,,,,
-508,176,i1,1704388700,1,1,37,-571542810_01,-571542797_02.99,571542797_02.99,571542810_01
-509,176,i1,1704388700,2,2,73,-571542810_01,-571542797_02.99,-571542810_01,571543469_01
-510,176,i1,1704388700,3,3,40,571543469_02,-571542797_02.99,,
-511,210,i6,1704388710,1,1,24,-571542115_01,571500535_01,,
-512,210,i6,1704388710,1,2,19,-571542115_01,571500535_01,571500535_02.18,571542115_01
-513,210,i6,1704388710,2,2,29,571500535_02.18,571511538_01,571500535_02.18,571542115_01
-514,210,i6,1704388710,3,3,56,571511538_02.121,571542115_01,571511538_02.121,571500585_01
-515,210,i6,1704388710,4,4,22,571500585_02,571511538_01,571500585_02,571500535_01
-516,175,i0,1704388720,1,1,37,-571542797_02,571500487_01,-571500487_01,571542797_02
-517,175,i0,1704388720,2,2,39,-571500487_01,571545870_01,-571542797_02,571510153_01
-518,175,i0,1704388720,3,3,25,571545870_02,571510153_01,571545870_02,571542797_02
-519,175,i0,1704388720,3,4,30,571545870_02,571510153_01,571510153_02,571545870_01
-520,175,i0,1704388720,4,4,29,571510153_02,571500487_01,571510153_02,571545870_01
-521,178,i3,1704388800,1,1,38,571540304_02,571556450_01,571556450_02,571540304_01
-522,178,i3,1704388800,2,2,39,571556450_02,571500475_01,571540304_02,571540303_01
-523,178,i3,1704388800,3,3,40,571540303_02.21,571556450_01,571540303_02.21,571500475_01
-524,178,i3,1704388800,4,4,23,-571500475_01,571540303_01,-571500475_01,571540304_01
-525,201,i8,1704388800,1,1,24,-571500569_01,571500583_02,-571500569_01,571500618_01
-526,201,i8,1704388800,2,2,24,571500618_02,571500583_02,571500618_02,571500617_01
-527,201,i8,1704388800,3,3,17,571500617_02,571500618_01,571500618_02,571500617_01
-528,201,i8,1704388800,4,4,58,571500617_02,571500618_01,571500617_02,571500569_01
-529,201,i8,1704388800,5,5,17,571500583_01,571500617_01,571500583_01,571500569_01
-530,206,i7,1704388800,1,1,33,-571511538_02,571542073_02,571542073_01,571511538_02
-531,206,i7,1704388800,2,2,35,,,,
-532,206,i7,1704388800,3,3,26,-571511538_02,571542073_02,571542073_01,571511538_02
-533,206,i7,1704388800,4,4,26,,,,
-534,176,i1,1704388850,1,1,37,-571542810_01,-571542797_02.99,571542797_02.99,571542810_01
-535,176,i1,1704388850,2,2,73,-571542810_01,-571542797_02.99,-571542810_01,571543469_01
-536,176,i1,1704388850,3,3,40,571543469_02,-571542797_02.99,,
-537,210,i6,1704388860,1,1,24,-571542115_01,571500535_01,,
-538,210,i6,1704388860,1,2,19,-571542115_01,571500535_01,571500535_02.18,571542115_01
-539,210,i6,1704388860,2,2,29,571500535_02.18,571511538_01,571500535_02.18,571542115_01
-540,210,i6,1704388860,3,3,56,571511538_02.121,571542115_01,571511538_02.121,571500585_01
-541,210,i6,1704388860,4,4,22,571500585_02,571511538_01,571500585_02,571500535_01
-542,175,i0,1704388880,1,1,37,-571542797_02,571500487_01,-571500487_01,571542797_02
-543,175,i0,1704388880,2,2,39,-571500487_01,571545870_01,-571542797_02,571510153_01
-544,175,i0,1704388880,3,3,25,571545870_02,571510153_01,571545870_02,571542797_02
-545,175,i0,1704388880,3,4,30,571545870_02,571510153_01,571510153_02,571545870_01
-546,175,i0,1704388880,4,4,29,571510153_02,571500487_01,571510153_02,571545870_01
-547,206,i7,1704388920,1,1,33,-571511538_02,571542073_02,571542073_01,571511538_02
-548,206,i7,1704388920,2,2,35,,,,
-549,206,i7,1704388920,3,3,26,-571511538_02,571542073_02,571542073_01,571511538_02
-550,206,i7,1704388920,4,4,26,,,,
-551,201,i8,1704388940,1,1,24,-571500569_01,571500583_02,-571500569_01,571500618_01
-552,201,i8,1704388940,2,2,24,571500618_02,571500583_02,571500618_02,571500617_01
-553,201,i8,1704388940,3,3,17,571500617_02,571500618_01,571500618_02,571500617_01
-554,201,i8,1704388940,4,4,58,571500617_02,571500618_01,571500617_02,571500569_01
-555,201,i8,1704388940,5,5,17,571500583_01,571500617_01,571500583_01,571500569_01
-556,177,i2,1704388950,1,1,36,-571542809_01,571542811_01,571542811_02,571542809_01
-557,177,i2,1704388950,2,2,20,571542811_02,571542107_01,-571542809_01,571542809_01
-558,177,i2,1704388950,3,3,68,,,,
-559,177,i2,1704388950,4,4,26,-571542809_01,571542811_01,571542107_02,571542809_01
-560,176,i1,1704389000,1,1,37,-571542810_01,-571542797_02.99,571542797_02.99,571542810_01
-561,176,i1,1704389000,2,2,73,-571542810_01,-571542797_02.99,-571542810_01,571543469_01
-562,176,i1,1704389000,3,3,40,571543469_02,-571542797_02.99,,
-563,210,i6,1704389010,1,1,24,-571542115_01,571500535_01,,
-564,210,i6,1704389010,1,2,19,-571542115_01,571500535_01,571500535_02.18,571542115_01
-565,210,i6,1704389010,2,2,29,571500535_02.18,571511538_01,571500535_02.18,571542115_01
-566,210,i6,1704389010,3,3,56,571511538_02.121,571542115_01,571511538_02.121,571500585_01
-567,210,i6,1704389010,4,4,22,571500585_02,571511538_01,571500585_02,571500535_01
-568,175,i0,1704389040,1,1,37,-571542797_02,571500487_01,-571500487_01,571542797_02
-569,175,i0,1704389040,2,2,39,-571500487_01,571545870_01,-571542797_02,571510153_01
-570,175,i0,1704389040,3,3,25,571545870_02,571510153_01,571545870_02,571542797_02
-571,175,i0,1704389040,3,4,30,571545870_02,571510153_01,571510153_02,571545870_01
-572,175,i0,1704389040,4,4,29,571510153_02,571500487_01,571510153_02,571545870_01
-573,206,i7,1704389040,1,1,33,-571511538_02,571542073_02,571542073_01,571511538_02
-574,206,i7,1704389040,2,2,35,,,,
-575,206,i7,1704389040,3,3,26,-571511538_02,571542073_02,571542073_01,571511538_02
-576,206,i7,1704389040,4,4,26,,,,
-577,201,i8,1704389080,1,1,24,-571500569_01,571500583_02,-571500569_01,571500618_01
-578,201,i8,1704389080,2,2,24,571500618_02,571500583_02,571500618_02,571500617_01
-579,201,i8,1704389080,3,3,17,571500617_02,571500618_01,571500618_02,571500617_01
-580,201,i8,1704389080,4,4,58,571500617_02,571500618_01,571500617_02,571500569_01
-581,201,i8,1704389080,5,5,17,571500583_01,571500617_01,571500583_01,571500569_01
-582,202,i9,1704389080,1,1,39,571510152_02,-571510152_01,571510152_01,571510152_01.65
-583,202,i9,1704389080,2,2,101,,,,
-584,177,i2,1704389100,1,1,36,-571542809_01,571542811_01,571542811_02,571542809_01
-585,177,i2,1704389100,2,2,20,571542811_02,571542107_01,-571542809_01,571542809_01
-586,177,i2,1704389100,3,3,68,,,,
-587,177,i2,1704389100,4,4,26,-571542809_01,571542811_01,571542107_02,571542809_01
-588,176,i1,1704389150,1,1,37,-571542810_01,-571542797_02.99,571542797_02.99,571542810_01
-589,176,i1,1704389150,2,2,73,-571542810_01,-571542797_02.99,-571542810_01,571543469_01
-590,176,i1,1704389150,3,3,40,571543469_02,-571542797_02.99,,
-591,206,i7,1704389160,1,1,33,-571511538_02,571542073_02,571542073_01,571511538_02
-592,206,i7,1704389160,2,2,35,,,,
-593,206,i7,1704389160,3,3,26,-571511538_02,571542073_02,571542073_01,571511538_02
-594,206,i7,1704389160,4,4,26,,,,
-595,210,i6,1704389160,1,1,24,-571542115_01,571500535_01,,
-596,210,i6,1704389160,1,2,19,-571542115_01,571500535_01,571500535_02.18,571542115_01
-597,210,i6,1704389160,2,2,29,571500535_02.18,571511538_01,571500535_02.18,571542115_01
-598,210,i6,1704389160,3,3,56,571511538_02.121,571542115_01,571511538_02.121,571500585_01
-599,210,i6,1704389160,4,4,22,571500585_02,571511538_01,571500585_02,571500535_01
-600,175,i0,1704389200,1,1,37,-571542797_02,571500487_01,-571500487_01,571542797_02
-601,175,i0,1704389200,2,2,39,-571500487_01,571545870_01,-571542797_02,571510153_01
-602,175,i0,1704389200,3,3,25,571545870_02,571510153_01,571545870_02,571542797_02
-603,175,i0,1704389200,3,4,30,571545870_02,571510153_01,571510153_02,571545870_01
-604,175,i0,1704389200,4,4,29,571510153_02,571500487_01,571510153_02,571545870_01
-605,178,i3,1704389220,1,1,38,571540304_02,571556450_01,571556450_02,571540304_01
-606,178,i3,1704389220,2,2,39,571556450_02,571500475_01,571540304_02,571540303_01
-607,178,i3,1704389220,3,3,40,571540303_02.21,571556450_01,571540303_02.21,571500475_01
-608,178,i3,1704389220,4,4,23,-571500475_01,571540303_01,-571500475_01,571540304_01
-609,202,i9,1704389220,1,1,39,571510152_02,-571510152_01,571510152_01,571510152_01.65
-610,202,i9,1704389220,2,2,101,,,,
+,inter_no,start_unix,dura_A1,dura_A2,dura_A3,dura_A4,dura_A5,dura_A6,dura_A7,dura_A8,dura_B1,dura_B2,dura_B3,dura_B4,dura_B5,dura_B6,dura_B7,dura_B8,cycle
+60,178,1704388800,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+60,201,1704388800,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+60,202,1704388800,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+70,206,1704388800,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+56,177,1704388801,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+56,176,1704388850,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+56,210,1704388860,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+53,175,1704388880,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+71,206,1704388920,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+61,202,1704388939,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+61,178,1704388940,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+61,201,1704388940,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+57,177,1704388950,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+57,176,1704389000,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+57,210,1704389010,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+54,175,1704389040,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+72,206,1704389040,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+62,201,1704389080,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+62,202,1704389080,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+62,178,1704389081,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+58,177,1704389100,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+58,176,1704389150,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+73,206,1704389160,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+58,210,1704389160,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+55,175,1704389200,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+63,178,1704389220,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+63,201,1704389220,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+63,202,1704389220,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+59,177,1704389250,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+74,206,1704389280,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+59,176,1704389300,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+59,210,1704389310,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+64,201,1704389359,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+56,175,1704389360,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+64,178,1704389360,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+64,202,1704389360,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+60,177,1704389400,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+75,206,1704389400,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+60,176,1704389450,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+60,210,1704389460,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+65,178,1704389500,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+65,201,1704389500,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+65,202,1704389500,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+57,175,1704389520,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+76,206,1704389520,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+61,177,1704389551,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+61,176,1704389599,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+61,210,1704389610,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+66,178,1704389640,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+66,201,1704389640,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+66,202,1704389640,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+77,206,1704389640,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+58,175,1704389680,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+62,177,1704389700,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+62,176,1704389750,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+62,210,1704389759,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+78,206,1704389760,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+67,201,1704389779,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+67,178,1704389780,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+67,202,1704389780,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+59,175,1704389839,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+63,177,1704389850,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+79,206,1704389880,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+63,176,1704389900,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+63,210,1704389910,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+68,178,1704389920,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+68,201,1704389920,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+68,202,1704389920,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+60,175,1704390000,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+64,177,1704390000,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+80,206,1704390000,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+64,176,1704390050,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+69,178,1704390060,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+69,201,1704390060,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+69,202,1704390060,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+64,210,1704390060,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+81,206,1704390120,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+65,177,1704390150,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+61,175,1704390160,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+65,176,1704390200,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+70,201,1704390200,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+70,202,1704390200,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+70,178,1704390201,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+65,210,1704390210,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+82,206,1704390240,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+66,177,1704390300,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+62,175,1704390320,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+71,178,1704390340,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+71,201,1704390340,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+71,202,1704390340,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+66,176,1704390349,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+83,206,1704390359,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+66,210,1704390360,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+67,177,1704390450,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+63,175,1704390480,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+72,178,1704390480,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+72,201,1704390480,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+84,206,1704390480,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+67,176,1704390500,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+67,210,1704390510,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+72,202,1704390529,53,136,0,0,0,0,0,0,53,136,0,0,0,0,0,0,189
+68,177,1704390599,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+85,206,1704390600,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+73,178,1704390620,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+73,201,1704390620,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+64,175,1704390640,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+68,176,1704390650,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+68,210,1704390660,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+73,202,1704390670,39,102,0,0,0,0,0,0,39,102,0,0,0,0,0,0,141
+86,206,1704390720,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+69,177,1704390750,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+74,201,1704390760,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+74,178,1704390761,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+65,175,1704390800,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+69,176,1704390800,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+69,210,1704390809,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+74,202,1704390810,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+87,206,1704390840,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+70,177,1704390900,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+75,178,1704390900,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+75,201,1704390900,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+70,176,1704390950,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+75,202,1704390950,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+66,175,1704390960,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+88,206,1704390960,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+70,210,1704390960,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+76,201,1704391040,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+76,178,1704391041,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+71,177,1704391050,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+89,206,1704391080,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+76,202,1704391090,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+71,176,1704391100,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+71,210,1704391110,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+67,175,1704391119,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+77,178,1704391180,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+77,201,1704391180,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+90,206,1704391200,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+72,177,1704391201,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+77,202,1704391230,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+72,176,1704391250,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+72,210,1704391260,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+68,175,1704391280,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+78,178,1704391320,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+78,201,1704391320,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+91,206,1704391320,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+73,177,1704391350,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+78,202,1704391370,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+73,176,1704391399,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+73,210,1704391410,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+69,175,1704391440,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+92,206,1704391440,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+79,201,1704391460,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+79,178,1704391461,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+74,177,1704391500,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+79,202,1704391509,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+74,176,1704391550,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+93,206,1704391560,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+74,210,1704391560,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+70,175,1704391600,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+80,178,1704391600,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+80,201,1704391600,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+75,177,1704391650,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+80,202,1704391650,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+94,206,1704391680,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+75,176,1704391700,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+75,210,1704391710,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+81,201,1704391740,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+81,178,1704391741,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+71,175,1704391760,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+81,202,1704391790,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+76,177,1704391800,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+95,206,1704391801,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+76,176,1704391850,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+76,210,1704391859,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+82,178,1704391880,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+82,201,1704391880,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+72,175,1704391920,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+96,206,1704391920,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+82,202,1704391930,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+77,177,1704391950,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+77,176,1704392000,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+77,210,1704392010,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+83,178,1704392020,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+83,201,1704392020,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+97,206,1704392040,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+83,202,1704392070,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+73,175,1704392080,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+78,177,1704392100,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+78,176,1704392151,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+78,210,1704392159,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+84,178,1704392160,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+84,201,1704392160,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+98,206,1704392160,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+84,202,1704392211,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
diff --git a/Data/tables/histids/histids_1704389700.csv b/Data/tables/histids/histids_1704389700.csv
index e9025ecb4..d8f6f5577 100644
--- a/Data/tables/histids/histids_1704389700.csv
+++ b/Data/tables/histids/histids_1704389700.csv
@@ -1,134 +1,195 @@
-,inter_no,node_id,start_unix,phas_A,phas_B,duration,inc_edge_A,out_edge_A,inc_edge_B,out_edge_B
-489,176,i1,1704388850,1,1,37,-571542810_01,-571542797_02.99,571542797_02.99,571542810_01
-490,176,i1,1704388850,2,2,73,-571542810_01,-571542797_02.99,-571542810_01,571543469_01
-491,176,i1,1704388850,3,3,40,571543469_02,-571542797_02.99,,
-492,210,i6,1704388860,1,1,24,-571542115_01,571500535_01,,
-493,210,i6,1704388860,1,2,19,-571542115_01,571500535_01,571500535_02.18,571542115_01
-494,210,i6,1704388860,2,2,29,571500535_02.18,571511538_01,571500535_02.18,571542115_01
-495,210,i6,1704388860,3,3,56,571511538_02.121,571542115_01,571511538_02.121,571500585_01
-496,210,i6,1704388860,4,4,22,571500585_02,571511538_01,571500585_02,571500535_01
-497,175,i0,1704388880,1,1,37,-571542797_02,571500487_01,-571500487_01,571542797_02
-498,175,i0,1704388880,2,2,39,-571500487_01,571545870_01,-571542797_02,571510153_01
-499,175,i0,1704388880,3,3,25,571545870_02,571510153_01,571545870_02,571542797_02
-500,175,i0,1704388880,3,4,30,571545870_02,571510153_01,571510153_02,571545870_01
-501,175,i0,1704388880,4,4,29,571510153_02,571500487_01,571510153_02,571545870_01
-502,206,i7,1704388920,1,1,33,-571511538_02,571542073_02,571542073_01,571511538_02
-503,206,i7,1704388920,2,2,35,,,,
-504,206,i7,1704388920,3,3,26,-571511538_02,571542073_02,571542073_01,571511538_02
-505,206,i7,1704388920,4,4,26,,,,
-506,201,i8,1704388940,1,1,24,-571500569_01,571500583_02,-571500569_01,571500618_01
-507,201,i8,1704388940,2,2,24,571500618_02,571500583_02,571500618_02,571500617_01
-508,201,i8,1704388940,3,3,17,571500617_02,571500618_01,571500618_02,571500617_01
-509,201,i8,1704388940,4,4,58,571500617_02,571500618_01,571500617_02,571500569_01
-510,201,i8,1704388940,5,5,17,571500583_01,571500617_01,571500583_01,571500569_01
-511,177,i2,1704388950,1,1,36,-571542809_01,571542811_01,571542811_02,571542809_01
-512,177,i2,1704388950,2,2,20,571542811_02,571542107_01,-571542809_01,571542809_01
-513,177,i2,1704388950,3,3,68,,,,
-514,177,i2,1704388950,4,4,26,-571542809_01,571542811_01,571542107_02,571542809_01
-515,176,i1,1704389000,1,1,37,-571542810_01,-571542797_02.99,571542797_02.99,571542810_01
-516,176,i1,1704389000,2,2,73,-571542810_01,-571542797_02.99,-571542810_01,571543469_01
-517,176,i1,1704389000,3,3,40,571543469_02,-571542797_02.99,,
-518,210,i6,1704389010,1,1,24,-571542115_01,571500535_01,,
-519,210,i6,1704389010,1,2,19,-571542115_01,571500535_01,571500535_02.18,571542115_01
-520,210,i6,1704389010,2,2,29,571500535_02.18,571511538_01,571500535_02.18,571542115_01
-521,210,i6,1704389010,3,3,56,571511538_02.121,571542115_01,571511538_02.121,571500585_01
-522,210,i6,1704389010,4,4,22,571500585_02,571511538_01,571500585_02,571500535_01
-523,175,i0,1704389040,1,1,37,-571542797_02,571500487_01,-571500487_01,571542797_02
-524,175,i0,1704389040,2,2,39,-571500487_01,571545870_01,-571542797_02,571510153_01
-525,175,i0,1704389040,3,3,25,571545870_02,571510153_01,571545870_02,571542797_02
-526,175,i0,1704389040,3,4,30,571545870_02,571510153_01,571510153_02,571545870_01
-527,175,i0,1704389040,4,4,29,571510153_02,571500487_01,571510153_02,571545870_01
-528,206,i7,1704389040,1,1,33,-571511538_02,571542073_02,571542073_01,571511538_02
-529,206,i7,1704389040,2,2,35,,,,
-530,206,i7,1704389040,3,3,26,-571511538_02,571542073_02,571542073_01,571511538_02
-531,206,i7,1704389040,4,4,26,,,,
-532,201,i8,1704389080,1,1,24,-571500569_01,571500583_02,-571500569_01,571500618_01
-533,201,i8,1704389080,2,2,24,571500618_02,571500583_02,571500618_02,571500617_01
-534,201,i8,1704389080,3,3,17,571500617_02,571500618_01,571500618_02,571500617_01
-535,201,i8,1704389080,4,4,58,571500617_02,571500618_01,571500617_02,571500569_01
-536,201,i8,1704389080,5,5,17,571500583_01,571500617_01,571500583_01,571500569_01
-537,202,i9,1704389080,1,1,39,571510152_02,-571510152_01,571510152_01,571510152_01.65
-538,202,i9,1704389080,2,2,101,,,,
-539,177,i2,1704389100,1,1,36,-571542809_01,571542811_01,571542811_02,571542809_01
-540,177,i2,1704389100,2,2,20,571542811_02,571542107_01,-571542809_01,571542809_01
-541,177,i2,1704389100,3,3,68,,,,
-542,177,i2,1704389100,4,4,26,-571542809_01,571542811_01,571542107_02,571542809_01
-543,176,i1,1704389150,1,1,37,-571542810_01,-571542797_02.99,571542797_02.99,571542810_01
-544,176,i1,1704389150,2,2,73,-571542810_01,-571542797_02.99,-571542810_01,571543469_01
-545,176,i1,1704389150,3,3,40,571543469_02,-571542797_02.99,,
-546,206,i7,1704389160,1,1,33,-571511538_02,571542073_02,571542073_01,571511538_02
-547,206,i7,1704389160,2,2,35,,,,
-548,206,i7,1704389160,3,3,26,-571511538_02,571542073_02,571542073_01,571511538_02
-549,206,i7,1704389160,4,4,26,,,,
-550,210,i6,1704389160,1,1,24,-571542115_01,571500535_01,,
-551,210,i6,1704389160,1,2,19,-571542115_01,571500535_01,571500535_02.18,571542115_01
-552,210,i6,1704389160,2,2,29,571500535_02.18,571511538_01,571500535_02.18,571542115_01
-553,210,i6,1704389160,3,3,56,571511538_02.121,571542115_01,571511538_02.121,571500585_01
-554,210,i6,1704389160,4,4,22,571500585_02,571511538_01,571500585_02,571500535_01
-555,175,i0,1704389200,1,1,37,-571542797_02,571500487_01,-571500487_01,571542797_02
-556,175,i0,1704389200,2,2,39,-571500487_01,571545870_01,-571542797_02,571510153_01
-557,175,i0,1704389200,3,3,25,571545870_02,571510153_01,571545870_02,571542797_02
-558,175,i0,1704389200,3,4,30,571545870_02,571510153_01,571510153_02,571545870_01
-559,175,i0,1704389200,4,4,29,571510153_02,571500487_01,571510153_02,571545870_01
-560,178,i3,1704389220,1,1,38,571540304_02,571556450_01,571556450_02,571540304_01
-561,178,i3,1704389220,2,2,39,571556450_02,571500475_01,571540304_02,571540303_01
-562,178,i3,1704389220,3,3,40,571540303_02.21,571556450_01,571540303_02.21,571500475_01
-563,178,i3,1704389220,4,4,23,-571500475_01,571540303_01,-571500475_01,571540304_01
-564,202,i9,1704389220,1,1,39,571510152_02,-571510152_01,571510152_01,571510152_01.65
-565,202,i9,1704389220,2,2,101,,,,
-566,177,i2,1704389250,1,1,36,-571542809_01,571542811_01,571542811_02,571542809_01
-567,177,i2,1704389250,2,2,20,571542811_02,571542107_01,-571542809_01,571542809_01
-568,177,i2,1704389250,3,3,68,,,,
-569,177,i2,1704389250,4,4,26,-571542809_01,571542811_01,571542107_02,571542809_01
-570,206,i7,1704389280,1,1,33,-571511538_02,571542073_02,571542073_01,571511538_02
-571,206,i7,1704389280,2,2,35,,,,
-572,206,i7,1704389280,3,3,26,-571511538_02,571542073_02,571542073_01,571511538_02
-573,206,i7,1704389280,4,4,26,,,,
-574,176,i1,1704389300,1,1,37,-571542810_01,-571542797_02.99,571542797_02.99,571542810_01
-575,176,i1,1704389300,2,2,73,-571542810_01,-571542797_02.99,-571542810_01,571543469_01
-576,176,i1,1704389300,3,3,40,571543469_02,-571542797_02.99,,
-577,210,i6,1704389310,1,1,24,-571542115_01,571500535_01,,
-578,210,i6,1704389310,1,2,19,-571542115_01,571500535_01,571500535_02.18,571542115_01
-579,210,i6,1704389310,2,2,29,571500535_02.18,571511538_01,571500535_02.18,571542115_01
-580,210,i6,1704389310,3,3,56,571511538_02.121,571542115_01,571511538_02.121,571500585_01
-581,210,i6,1704389310,4,4,22,571500585_02,571511538_01,571500585_02,571500535_01
-582,175,i0,1704389360,1,1,37,-571542797_02,571500487_01,-571500487_01,571542797_02
-583,175,i0,1704389360,2,2,39,-571500487_01,571545870_01,-571542797_02,571510153_01
-584,175,i0,1704389360,3,3,25,571545870_02,571510153_01,571545870_02,571542797_02
-585,175,i0,1704389360,3,4,30,571545870_02,571510153_01,571510153_02,571545870_01
-586,175,i0,1704389360,4,4,29,571510153_02,571500487_01,571510153_02,571545870_01
-587,178,i3,1704389360,1,1,38,571540304_02,571556450_01,571556450_02,571540304_01
-588,178,i3,1704389360,2,2,39,571556450_02,571500475_01,571540304_02,571540303_01
-589,178,i3,1704389360,3,3,40,571540303_02.21,571556450_01,571540303_02.21,571500475_01
-590,178,i3,1704389360,4,4,23,-571500475_01,571540303_01,-571500475_01,571540304_01
-591,202,i9,1704389360,1,1,39,571510152_02,-571510152_01,571510152_01,571510152_01.65
-592,202,i9,1704389360,2,2,101,,,,
-593,206,i7,1704389400,1,1,33,-571511538_02,571542073_02,571542073_01,571511538_02
-594,206,i7,1704389400,2,2,35,,,,
-595,206,i7,1704389400,3,3,26,-571511538_02,571542073_02,571542073_01,571511538_02
-596,206,i7,1704389400,4,4,26,,,,
-597,210,i6,1704389460,1,1,24,-571542115_01,571500535_01,,
-598,210,i6,1704389460,1,2,19,-571542115_01,571500535_01,571500535_02.18,571542115_01
-599,210,i6,1704389460,2,2,29,571500535_02.18,571511538_01,571500535_02.18,571542115_01
-600,210,i6,1704389460,3,3,56,571511538_02.121,571542115_01,571511538_02.121,571500585_01
-601,210,i6,1704389460,4,4,22,571500585_02,571511538_01,571500585_02,571500535_01
-602,178,i3,1704389500,1,1,38,571540304_02,571556450_01,571556450_02,571540304_01
-603,178,i3,1704389500,2,2,39,571556450_02,571500475_01,571540304_02,571540303_01
-604,178,i3,1704389500,3,3,40,571540303_02.21,571556450_01,571540303_02.21,571500475_01
-605,178,i3,1704389500,4,4,23,-571500475_01,571540303_01,-571500475_01,571540304_01
-606,201,i8,1704389500,1,1,24,-571500569_01,571500583_02,-571500569_01,571500618_01
-607,201,i8,1704389500,2,2,24,571500618_02,571500583_02,571500618_02,571500617_01
-608,201,i8,1704389500,3,3,17,571500617_02,571500618_01,571500618_02,571500617_01
-609,201,i8,1704389500,4,4,58,571500617_02,571500618_01,571500617_02,571500569_01
-610,201,i8,1704389500,5,5,17,571500583_01,571500617_01,571500583_01,571500569_01
-611,202,i9,1704389500,1,1,39,571510152_02,-571510152_01,571510152_01,571510152_01.65
-612,202,i9,1704389500,2,2,101,,,,
-613,175,i0,1704389520,1,1,37,-571542797_02,571500487_01,-571500487_01,571542797_02
-614,175,i0,1704389520,2,2,39,-571500487_01,571545870_01,-571542797_02,571510153_01
-615,175,i0,1704389520,3,3,25,571545870_02,571510153_01,571545870_02,571542797_02
-616,175,i0,1704389520,3,4,30,571545870_02,571510153_01,571510153_02,571545870_01
-617,175,i0,1704389520,4,4,29,571510153_02,571500487_01,571510153_02,571545870_01
-618,206,i7,1704389520,1,1,33,-571511538_02,571542073_02,571542073_01,571511538_02
-619,206,i7,1704389520,2,2,35,,,,
-620,206,i7,1704389520,3,3,26,-571511538_02,571542073_02,571542073_01,571511538_02
-621,206,i7,1704389520,4,4,26,,,,
+,inter_no,start_unix,dura_A1,dura_A2,dura_A3,dura_A4,dura_A5,dura_A6,dura_A7,dura_A8,dura_B1,dura_B2,dura_B3,dura_B4,dura_B5,dura_B6,dura_B7,dura_B8,cycle
+60,178,1704388800,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+60,201,1704388800,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+60,202,1704388800,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+70,206,1704388800,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+56,177,1704388801,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+56,176,1704388850,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+56,210,1704388860,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+53,175,1704388880,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+71,206,1704388920,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+61,202,1704388939,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+61,178,1704388940,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+61,201,1704388940,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+57,177,1704388950,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+57,176,1704389000,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+57,210,1704389010,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+54,175,1704389040,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+72,206,1704389040,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+62,201,1704389080,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+62,202,1704389080,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+62,178,1704389081,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+58,177,1704389100,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+58,176,1704389150,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+73,206,1704389160,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+58,210,1704389160,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+55,175,1704389200,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+63,178,1704389220,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+63,201,1704389220,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+63,202,1704389220,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+59,177,1704389250,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+74,206,1704389280,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+59,176,1704389300,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+59,210,1704389310,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+64,201,1704389359,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+56,175,1704389360,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+64,178,1704389360,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+64,202,1704389360,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+60,177,1704389400,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+75,206,1704389400,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+60,176,1704389450,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+60,210,1704389460,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+65,178,1704389500,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+65,201,1704389500,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+65,202,1704389500,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+57,175,1704389520,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+76,206,1704389520,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+61,177,1704389551,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+61,176,1704389599,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+61,210,1704389610,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+66,178,1704389640,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+66,201,1704389640,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+66,202,1704389640,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+77,206,1704389640,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+58,175,1704389680,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+62,177,1704389700,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+62,176,1704389750,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+62,210,1704389759,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+78,206,1704389760,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+67,201,1704389779,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+67,178,1704389780,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+67,202,1704389780,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+59,175,1704389839,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+63,177,1704389850,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+79,206,1704389880,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+63,176,1704389900,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+63,210,1704389910,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+68,178,1704389920,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+68,201,1704389920,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+68,202,1704389920,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+60,175,1704390000,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+64,177,1704390000,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+80,206,1704390000,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+64,176,1704390050,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+69,178,1704390060,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+69,201,1704390060,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+69,202,1704390060,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+64,210,1704390060,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+81,206,1704390120,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+65,177,1704390150,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+61,175,1704390160,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+65,176,1704390200,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+70,201,1704390200,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+70,202,1704390200,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+70,178,1704390201,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+65,210,1704390210,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+82,206,1704390240,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+66,177,1704390300,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+62,175,1704390320,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+71,178,1704390340,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+71,201,1704390340,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+71,202,1704390340,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+66,176,1704390349,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+83,206,1704390359,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+66,210,1704390360,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+67,177,1704390450,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+63,175,1704390480,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+72,178,1704390480,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+72,201,1704390480,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+84,206,1704390480,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+67,176,1704390500,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+67,210,1704390510,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+72,202,1704390529,53,136,0,0,0,0,0,0,53,136,0,0,0,0,0,0,189
+68,177,1704390599,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+85,206,1704390600,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+73,178,1704390620,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+73,201,1704390620,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+64,175,1704390640,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+68,176,1704390650,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+68,210,1704390660,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+73,202,1704390670,39,102,0,0,0,0,0,0,39,102,0,0,0,0,0,0,141
+86,206,1704390720,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+69,177,1704390750,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+74,201,1704390760,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+74,178,1704390761,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+65,175,1704390800,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+69,176,1704390800,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+69,210,1704390809,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+74,202,1704390810,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+87,206,1704390840,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+70,177,1704390900,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+75,178,1704390900,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+75,201,1704390900,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+70,176,1704390950,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+75,202,1704390950,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+66,175,1704390960,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+88,206,1704390960,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+70,210,1704390960,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+76,201,1704391040,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+76,178,1704391041,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+71,177,1704391050,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+89,206,1704391080,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+76,202,1704391090,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+71,176,1704391100,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+71,210,1704391110,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+67,175,1704391119,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+77,178,1704391180,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+77,201,1704391180,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+90,206,1704391200,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+72,177,1704391201,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+77,202,1704391230,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+72,176,1704391250,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+72,210,1704391260,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+68,175,1704391280,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+78,178,1704391320,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+78,201,1704391320,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+91,206,1704391320,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+73,177,1704391350,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+78,202,1704391370,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+73,176,1704391399,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+73,210,1704391410,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+69,175,1704391440,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+92,206,1704391440,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+79,201,1704391460,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+79,178,1704391461,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+74,177,1704391500,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+79,202,1704391509,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+74,176,1704391550,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+93,206,1704391560,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+74,210,1704391560,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+70,175,1704391600,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+80,178,1704391600,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+80,201,1704391600,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+75,177,1704391650,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+80,202,1704391650,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+94,206,1704391680,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+75,176,1704391700,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+75,210,1704391710,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+81,201,1704391740,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+81,178,1704391741,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+71,175,1704391760,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+81,202,1704391790,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+76,177,1704391800,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+95,206,1704391801,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+76,176,1704391850,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+76,210,1704391859,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+82,178,1704391880,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+82,201,1704391880,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+72,175,1704391920,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+96,206,1704391920,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+82,202,1704391930,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+77,177,1704391950,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+77,176,1704392000,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+77,210,1704392010,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+83,178,1704392020,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+83,201,1704392020,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+97,206,1704392040,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+83,202,1704392070,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
+73,175,1704392080,37,39,55,29,0,0,0,0,37,39,25,59,0,0,0,0,160
+78,177,1704392100,36,20,68,26,0,0,0,0,36,20,68,26,0,0,0,0,150
+78,176,1704392151,37,73,40,0,0,0,0,0,37,73,40,0,0,0,0,0,150
+78,210,1704392159,43,29,56,22,0,0,0,0,24,48,56,22,0,0,0,0,150
+84,178,1704392160,38,39,40,23,0,0,0,0,38,39,40,23,0,0,0,0,140
+84,201,1704392160,24,24,17,58,17,0,0,0,24,24,17,58,17,0,0,0,140
+98,206,1704392160,33,35,26,26,0,0,0,0,33,35,26,26,0,0,0,0,120
+84,202,1704392211,39,101,0,0,0,0,0,0,39,101,0,0,0,0,0,0,140
diff --git a/Data/tables/movements/movements.csv b/Data/tables/movements/movements.csv
new file mode 100644
index 000000000..4d6c3e2bb
--- /dev/null
+++ b/Data/tables/movements/movements.csv
@@ -0,0 +1,33 @@
+,inter_no,phas_A,phas_B,move_A,move_B
+0,175,1,1,8,4
+1,175,2,2,7,3
+2,175,3,3,6,1
+3,175,3,4,6,2
+4,175,4,4,5,2
+5,176,1,1,8,4
+6,176,2,2,8,3
+7,176,3,3,5,18
+8,177,1,1,8,4
+9,177,2,2,7,3
+10,177,3,3,17,18
+11,177,4,4,5,1
+12,178,1,1,8,4
+13,178,2,2,7,3
+14,178,3,3,5,2
+15,178,4,4,6,1
+16,201,1,1,8,3
+17,201,2,2,5,2
+18,201,3,3,6,2
+19,201,4,4,6,1
+20,201,5,5,7,4
+21,202,1,1,6,2
+22,202,2,2,17,18
+23,206,1,1,8,4
+24,206,2,2,17,18
+25,206,3,3,8,4
+26,206,4,4,17,18
+27,210,1,1,6,18
+28,210,1,2,6,2
+29,210,2,2,5,2
+30,210,3,3,7,4
+31,210,4,4,8,3
diff --git a/Data/tables/moves/match1.csv b/Data/tables/moves/match1.csv
new file mode 100644
index 000000000..4d6c3e2bb
--- /dev/null
+++ b/Data/tables/moves/match1.csv
@@ -0,0 +1,33 @@
+,inter_no,phas_A,phas_B,move_A,move_B
+0,175,1,1,8,4
+1,175,2,2,7,3
+2,175,3,3,6,1
+3,175,3,4,6,2
+4,175,4,4,5,2
+5,176,1,1,8,4
+6,176,2,2,8,3
+7,176,3,3,5,18
+8,177,1,1,8,4
+9,177,2,2,7,3
+10,177,3,3,17,18
+11,177,4,4,5,1
+12,178,1,1,8,4
+13,178,2,2,7,3
+14,178,3,3,5,2
+15,178,4,4,6,1
+16,201,1,1,8,3
+17,201,2,2,5,2
+18,201,3,3,6,2
+19,201,4,4,6,1
+20,201,5,5,7,4
+21,202,1,1,6,2
+22,202,2,2,17,18
+23,206,1,1,8,4
+24,206,2,2,17,18
+25,206,3,3,8,4
+26,206,4,4,17,18
+27,210,1,1,6,18
+28,210,1,2,6,2
+29,210,2,2,5,2
+30,210,3,3,7,4
+31,210,4,4,8,3