{ "cells": [ { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "import os, sumolib\n", "import pandas as pd\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "from matplotlib_venn import venn2, venn3\n", "from datetime import datetime" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "class DailyPreprocessor:\n", " def __init__(self, config_name='revised', nowTime=datetime.now()):\n", " self.config_name = config_name\n", " self.nowTime = nowTime\n", "self = DailyPreprocessor(nowTime = datetime.now())" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "self.net = sumolib.net.readNet('new_sungnam_network_internal_target_0811.net.xml')" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "# ## 교차로목록 정의\n", "# sixties = pd.read_excel('교차로기반정보_(시범지역).xlsx', header=1)\n", "# self.inter_nos = set(sixties['교차로 ID'].dropna().astype(int))\n", "# # 551, 561은 TC_IF_TOD_RED_YELLO, TN_IF_SIGL_FLOW에 존재하지 않음. TOD 보고서에서도 확인할 수 없음\n", "# # 551 : 보육시설 삼거리, 561 : 공영주차장 단일로\n", "\n", "\n", "# self.inter_nos = self.inter_nos - {551, 561}\n", "# # 464는 매칭테이블에 존재하지 않음. 500에 매칭되는 node_id가 네트워크에 존재하지 않음.\n", "# # 464 : 성남공판장 단일로, 500 : 단남아파트 단일로\n", "# self.inter_nos = self.inter_nos - {464, 500}\n", "# print(len(self.inter_nos))\n", "# inter_nos_display = \", \".join(map(str, sorted(self.inter_nos)))\n", "# inter_nos_display = \"\\n\".join([inter_nos_display[i:i+100] for i in range(0, len(inter_nos_display), 100)])\n", "# # print(len(inter_nos_display))\n", "# print(inter_nos_display)" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [], "source": [ "## 매칭테이블 정의, 교차로-노드 딕셔너리 정의\n", "self.inter_node = pd.read_excel('signal_node_matching.xlsx', dtype={'node_id':str})\n", "self.inter_node = self.inter_node.rename(columns={'signal_id':'inter_no'})\n", "self.inter_node['inter_type'] = 'parent'\n", "self.inter_node = self.inter_node[self.inter_node.node_id.isin(node.getID() for node in self.net.getNodes())]" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "## 매칭테이블 정의, 교차로-노드 딕셔너리 정의\n", "self.inter_node = pd.read_excel('signal_node_matching.xlsx', dtype={'node_id':str})\n", "self.inter_node = self.inter_node.rename(columns={'signal_id':'inter_no'})\n", "self.inter_node['inter_type'] = 'parent'\n", "# self.inter_node = self.inter_node[self.inter_node.inter_no.isin(self.inter_nos)].reset_index(drop=True)\n", "self.inter_nos = sorted(self.inter_node.inter_no)\n", "\n", "# 일대일대응 확인\n", "if not len(self.inter_node) == self.inter_node.inter_no.nunique() == self.inter_node.node_id.nunique():\n", " raise ValueError(\"Warning: 'inter_no'와 'node_id' 간에 일대일대응 관계가 성립하지 않습니다.\")\n", "\n", "# 교차로번호 vs 노드id 간 딕셔너리\n", "self.inter2node = dict(zip(self.inter_node.inter_no, self.inter_node.node_id))\n", "self.node2inter = dict(zip(self.inter_node.node_id, self.inter_node.inter_no))\n", "self.node_ids = {self.inter2node[inter_no] for inter_no in self.inter_nos}" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "# net = sumolib.net.readNet('new_sungnam_network_internal_0809.net.xml')\n", "# inter_node = pd.read_excel('signal_node_matching.xlsx', dtype={'node_id':str})\n", "# print(len(set(inter_node.signal_id)))\n", "# print(inter_nos - set(inter_node.signal_id))\n", "# inter_node = inter_node[inter_node.node_id.isin(node.getID() for node in net.getNodes())]\n", "# print(len(set(inter_node.signal_id)))\n", "# print(inter_nos - set(inter_node.signal_id))" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "## 테이블 표준화\n", "\n", "# 주요 테이블 로드 (실제로는 쿼리문 작성 부분이 되어야 함.)\n", "self.dayplan = pd.read_csv(os.path.join(os.path.abspath('.'), 'sn_admin_tables', 'TC_IF_TOD_DAY_PLAN.csv'))\n", "self.holyplan = pd.read_csv(os.path.join(os.path.abspath('.'), 'sn_admin_tables', 'TC_IF_TOD_HOLIDAY_PLAN.csv'))\n", "self.red_yel = pd.read_csv(os.path.join(os.path.abspath('.'), 'sn_admin_tables', 'TC_IF_TOD_RED_YELLO.csv'))\n", "self.weekplan = pd.read_csv(os.path.join(os.path.abspath('.'), 'sn_admin_tables', 'TC_IF_TOD_WEEK_PLAN.csv'))\n", "# 교차로정보 테이블은 불러오지 않음 (해당 테이블이 실질적으로 쓰이지는 않고, 60개 테이블 정보가 있지도 않음)\n", "# inter_info=pd.read_csv(os.path.join(os.path.abspath('.'), 'sn_admin_tables', 'TM_FA_CRSRD.csv'))\n", "self.flows = pd.read_csv(os.path.join(os.path.abspath('.'), 'sn_admin_tables', 'TN_IF_SIGL_FLOW.csv'))\n", "\n", "# 유효한 교차로들에 대하여만 슬라이싱\n", "self.dayplan = self.dayplan[self.dayplan.CRSRD_ID.isin(self.inter_nos)]\n", "self.weekplan= self.weekplan[self.weekplan.CRSRD_ID.isin(self.inter_nos)]\n", "self.red_yel = self.red_yel[self.red_yel.CRSRD_ID.isin(self.inter_nos)]\n", "self.flows = self.flows[self.flows.CRSRD_ID.isin(self.inter_nos)]\n", "\n", "# 컬럼명 변경 적용\n", "rename_cname_1 = {'CRSRD_ID':'inter_no', 'CYCL':'cycle', 'DAY':'DD',\n", " 'HOUR':'hh', 'MIN':'mm', 'MNTH':'MM',\n", " 'OFFSET':'offset', 'PHASE':'phase_no', 'PLAN_NO':'plan_no',\n", " 'RINGA_RED_SEC':'red_A', 'RINGA_YELLO_SEC':'yel_A', 'RINGB_RED_SEC':'red_B',\n", " 'RINGB_YELLO_SEC':'yel_B'}\n", "\n", "rename_cname_2 = {f'RING{alph}_PHASE{i}':f'dura_{alph}{i}' for alph in ['A', 'B'] for i in range(1,9)}\n", "rename_cname = {**rename_cname_1, **rename_cname_2}\n", "self.dayplan = self.dayplan.rename(columns=rename_cname)\n", "self.holyplan = self.holyplan.rename(columns=rename_cname)\n", "self.weekplan = self.weekplan.rename(columns=rename_cname)\n", "self.red_yel = self.red_yel.rename(columns=rename_cname)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "## self.plan : 신호계획 테이블 생성\n", "\n", "# 날짜, 요일 지정\n", "MM, DD = self.nowTime.month, self.nowTime.day # 날짜\n", "dow_number = self.nowTime.weekday() # 요일\n", "hplan = self.holyplan[(self.holyplan.MM==MM) & (self.holyplan.DD==DD)]\n", "dows = [dow for dow in self.weekplan.columns if dow.endswith('PLAN_NO')]\n", "dows = dows[1:] + dows[0:1]\n", "dow = dows[dow_number]\n", "\n", "# (신호교차로, 신호계획번호) 목록\n", "if len(hplan):\n", " inter_pnos = list(zip(hplan['inter_no'], hplan['plan_no']))\n", "else:\n", " inter_pnos = list(zip(self.weekplan.inter_no, self.weekplan[dow]))\n", "\n", "# 신호테이블 통합\n", "self.plan = self.dayplan.copy()\n", "self.plan['inter_pno'] = list(zip(self.plan['inter_no'], self.plan['plan_no']))\n", "self.plan = self.plan[(self.plan.inter_pno.isin(inter_pnos))]\n", "self.plan = self.plan.drop(columns='inter_pno')\n", "max_phase_no = int(self.red_yel.phase_no.max())\n", "for j in range(1,max_phase_no+1):\n", " RY = self.red_yel[self.red_yel.phase_no==j].iloc[0]\n", " red_A = RY.red_A\n", " red_B = RY.red_B\n", " yel_A = RY.yel_A\n", " yel_B = RY.yel_B\n", " self.plan[f'red_A{j}'] = red_A\n", " self.plan[f'red_B{j}'] = red_B\n", " self.plan[f'yellow_A{j}'] = yel_A\n", " self.plan[f'yellow_B{j}'] = yel_B" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\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", " \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", " \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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
inter_nophase_noring_typemove_noSTOS_NOangle_code
04361A50262358
14361B20262074
24362A80174355
34362B30172263
44363A70356074
.....................
3546394A60120312
3556394B10126221
3566401A80226052
3576401B40043222
3586402A170None
\n", "

359 rows × 6 columns

\n", "
" ], "text/plain": [ " inter_no phase_no ring_type move_no STOS_NO angle_code\n", "0 436 1 A 5 0 262358\n", "1 436 1 B 2 0 262074\n", "2 436 2 A 8 0 174355\n", "3 436 2 B 3 0 172263\n", "4 436 3 A 7 0 356074\n", ".. ... ... ... ... ... ...\n", "354 639 4 A 6 0 120312\n", "355 639 4 B 1 0 126221\n", "356 640 1 A 8 0 226052\n", "357 640 1 B 4 0 043222\n", "358 640 2 A 17 0 None\n", "\n", "[359 rows x 6 columns]" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "## self.angle : 각도(이동류방향) 테이블 생성\n", "self.angle = self.flows.copy()\n", "self.angle = self.angle.rename(columns={'CRSRD_ID':'inter_no', 'PHASE':'phase_no',\n", " 'RING':'ring_type', 'FLOW_NO':'move_no'})\n", "# 유효한 이동류번호 및 교차로번호로 슬라이싱\n", "self.angle = self.angle[self.angle.move_no.isin(range(1,19))]\n", "self.angle = self.angle[self.angle.inter_no.isin(self.inter_nos)]\n", "# 세 점 데이터 파싱 및 각도코드 열 생성\n", "for ind, row in self.angle.iterrows():\n", " arrow = row.SIGL_ARROW\n", " # 위경도 추출\n", " # arrow = re.findall(r'-?\\d+\\.?\\d*', arrow)\n", " arrow = [coord.lstrip(' ') for coord in arrow.split(',')]\n", " arrow = [coord.lstrip('[') for coord in arrow]\n", " arrow = [coord.rstrip(']') for coord in arrow]\n", " exists = all([bool(coord) for coord in arrow])\n", " if exists:\n", " y1, x1, y2, x2, y3, x3 = arrow\n", "\n", " # 미터 단위로 변환\n", " x1, y1 = self.net.convertLonLat2XY(x1, y1)\n", " x2, y2 = self.net.convertLonLat2XY(x2, y2)\n", " x3, y3 = self.net.convertLonLat2XY(x3, y3)\n", "\n", " # 진입각, 진출각 설정\n", " inc_angle = np.arctan2(y1 - y2, x1 - x2)\n", " out_angle = np.arctan2(y3 - y2, x3 - x2)\n", " inc_angle = inc_angle * 180 / np.pi\n", " out_angle = out_angle * 180 / np.pi\n", " inc_angle = int((90 - inc_angle) % 360)\n", " out_angle = int((90 - out_angle) % 360)\n", "\n", " # 각도코드 설정\n", " angle_code = str(inc_angle).zfill(3) + str(out_angle).zfill(3)\n", " self.angle.loc[ind, 'angle_code'] = angle_code\n", " else:\n", " self.angle.loc[ind, 'angle_code'] = None\n", "self.angle = self.angle.drop(columns='SIGL_ARROW')\n", "self.angle = self.angle.reset_index(drop=True)\\\n", " .sort_values(by=['inter_no', 'phase_no', 'ring_type']).reset_index(drop=True)\n", "self.angle" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\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", " \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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
inter_nophase_noring_typemove_no
04361A5
14361B2
24362A8
34362B3
44363A7
...............
3675762B17
3685822B17
3696322B17
3706344B5
3716402B17
\n", "

372 rows × 4 columns

\n", "
" ], "text/plain": [ " inter_no phase_no ring_type move_no\n", "0 436 1 A 5\n", "1 436 1 B 2\n", "2 436 2 A 8\n", "3 436 2 B 3\n", "4 436 3 A 7\n", ".. ... ... ... ...\n", "367 576 2 B 17\n", "368 582 2 B 17\n", "369 632 2 B 17\n", "370 634 4 B 5\n", "371 640 2 B 17\n", "\n", "[372 rows x 4 columns]" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
\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", " \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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
inter_nophase_noring_typemove_no
04361A5
14361B2
24362A8
34362B3
44363A7
...............
3675762B17
3685822B17
3696322B17
3706344B5
3716402B17
\n", "

372 rows × 4 columns

\n", "
" ], "text/plain": [ " inter_no phase_no ring_type move_no\n", "0 436 1 A 5\n", "1 436 1 B 2\n", "2 436 2 A 8\n", "3 436 2 B 3\n", "4 436 3 A 7\n", ".. ... ... ... ...\n", "367 576 2 B 17\n", "368 582 2 B 17\n", "369 632 2 B 17\n", "370 634 4 B 5\n", "371 640 2 B 17\n", "\n", "[372 rows x 4 columns]" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "## self.match1 테이블 생성\n", "match1 = self.flows.copy()\n", "match1 = match1[['CRSRD_ID', 'PHASE', 'RING', 'FLOW_NO']]\n", "match1 = match1.rename(columns={'CRSRD_ID':'inter_no', 'PHASE':'phase_no', 'RING':'ring_type', 'FLOW_NO':'move_no'})\n", "match1 = match1.sort_values(by=['inter_no', 'phase_no', 'ring_type']).reset_index(drop=True)\n", "# 유효한 이동류번호 및 교차로번호로 슬라이싱\n", "match1 = match1[match1.move_no.isin(range(1,19))]\n", "match1 = match1[match1.inter_no.isin(self.inter_nos)]\n", "# 특정한 (교차로번호, 현시번호)에 대하여 한 링에 대해서만 이동류번호만 정의된 경우, 나머지 링에 대해서 이동류 정의\n", "additional_m1s = []\n", "for key, group in match1.groupby(['inter_no', 'phase_no']):\n", " inter_no, phase_no = map(int,key)\n", " if set(group.ring_type) != {'A', 'B'}:\n", " assert len(group)==1\n", " ring_type = group.iloc[0].ring_type\n", " RING_TYPE = list({'A', 'B'} - set(ring_type))[0]\n", " additional_m1 = group.copy()\n", " additional_m1['ring_type'] = RING_TYPE\n", " additional_m1s.append(additional_m1)\n", "match1 = pd.concat([match1] + additional_m1s)\n", "match1 = match1.reset_index(drop=True)\n", "display(match1)\n", "# 열 재편 : 현시시간과 이동류번호 열을 A, B로 구분\n", "match1s = []\n", "for key, group in match1.copy().groupby(['inter_no', 'phase_no']):\n", " inter_no, phase_no = map(int, key)\n", " assert len(group) == 2\n", " row_A = group[group.ring_type=='A']\n", " row_B = group[group.ring_type=='B']\n", " assert len(row_A)==len(row_B)==1\n", " row_A = row_A.iloc[0]\n", " row_B = row_B.iloc[0]\n", " m1 = pd.DataFrame({'inter_no':[inter_no], 'phas_A':[phase_no], 'phas_B':[phase_no],\n", " 'move_A':[row_A.move_no], 'move_B':[row_B.move_no]})\n", " match1s.append(m1)\n", "display(match1)\n", "self.match1 = pd.concat(match1s).reset_index(drop=True)" ] }, { "cell_type": "code", "execution_count": 73, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['make_intermediates.ipynb',\n", " 'new_sungnam_network_internal_0809.net.xml',\n", " 'new_sungnam_network_internal_0811.net.xml',\n", " 'new_sungnam_network_internal_target_0811.net.xml',\n", " 'nodes.json',\n", " 'signal_node_matching.xlsx',\n", " 'signal_node_matching_0809.xlsx',\n", " 'sn_admin_tables',\n", " 'turn_type_info.csv',\n", " 'uturn_data_info.csv',\n", " '교차로기반정보_(시범지역).xlsx']" ] }, "execution_count": 73, "metadata": {}, "output_type": "execute_result" } ], "source": [ "os.listdir()" ] }, { "cell_type": "code", "execution_count": 78, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\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", " \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", " \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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
child_idcondition
0109187좌회전시
1109188좌회전시
2109189좌회전시
3109192좌회전시
4109193좌회전시
5109595좌회전시
6107169좌회전시
7108093좌회전시
8108098좌회전시
9108102좌회전시
10108099좌회전시
11108106좌회전시
12107717좌회전시
13110754좌회전시
14109205좌회전시
15107270좌회전시
\n", "
" ], "text/plain": [ " child_id condition\n", "0 109187 좌회전시\n", "1 109188 좌회전시\n", "2 109189 좌회전시\n", "3 109192 좌회전시\n", "4 109193 좌회전시\n", "5 109595 좌회전시\n", "6 107169 좌회전시\n", "7 108093 좌회전시\n", "8 108098 좌회전시\n", "9 108102 좌회전시\n", "10 108099 좌회전시\n", "11 108106 좌회전시\n", "12 107717 좌회전시\n", "13 110754 좌회전시\n", "14 109205 좌회전시\n", "15 107270 좌회전시" ] }, "execution_count": 78, "metadata": {}, "output_type": "execute_result" } ], "source": [ "self.uturn = pd.read_csv('uturn_data_info.csv')\n", "self.u_condition = self.uturn.copy()[['child_id']]\n", "self.u_condition['condition'] = '좌회전시'\n", "self.u_condition" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "# # self.coord : 연등교차로 테이블 생성\n", "# self.coord = pd.DataFrame(columns=['parent_id', 'child_id', 'phase_no', 'ring_type', 'inc_edge_id', 'out_edge_id'])" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "# dfs = {'dayplan':dayplan, 'red_yel':red_yel, 'weekplan':weekplan, 'flows':flows}\n", "# for df_name, df in dfs.items():\n", "# print(df_name)\n", "# assert set(df.CRSRD_ID).issubset(inter_nos)\n", "# inter_no_coincide = inter_nos == set(df.CRSRD_ID)\n", "# if not inter_no_coincide:\n", "# print(f\" inter_no's doesn't conicide.\")\n", "# print(f\" missing inter_no's : {inter_nos - set(df.CRSRD_ID)}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# venn3([set(dayplan.CRSRD_ID), set(red_yel.CRSRD_ID), set(weekplan.CRSRD_ID)], ('dayplan', 'redyel', 'weekplan'))\n", "# plt.show()\n", "# print(f'일간계획 테이블의 교차로 개수 : {len(set(dayplan.CRSRD_ID))}')\n", "# print(f'황색적색 테이블의 교차로 개수 : {len(set(red_yel.CRSRD_ID))}')\n", "# print(f'주간계획 테이블의 교차로 개수 : {len(set(weekplan.CRSRD_ID))}')\n", "# CRSRD_IDs_plan = set(dayplan.CRSRD_ID) & set(red_yel.CRSRD_ID) & set(weekplan.CRSRD_ID)\n", "# print(f'겹치는 교차로 개수 : {len(CRSRD_IDs_plan)}')\n", "# print(f'겹치는 교차로 목록 : {sorted(CRSRD_IDs_plan)}')" ] } ], "metadata": { "kernelspec": { "display_name": "siggen_env", "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.12.4" } }, "nbformat": 4, "nbformat_minor": 2 }