├── 2018_IBUS
├── README.md
└── data
│ ├── demand_G.gz
│ ├── new_road_G.gz
│ ├── road_network.gz
│ └── 정류소현황목록_20190924.xlsx
├── README.md
└── 속도네트워크 구축
├── excel_정류소현황목록.xlsx
├── 노선별 정류장 경유리스트.xls
├── 속도네트워크 구축.ipynb
└── BMS 데이터를 이용한 노선도 및 노선운행시간 예측.ipynb
/2018_IBUS/README.md:
--------------------------------------------------------------------------------
1 | # 2018-I-BUS
2 | # Mobility_Project
3 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Mobility_Project
2 | 정류소 현황데이터, 교통카드 데이터, BMS 데이터를 기반으로한 개별 시내버스노선 최적화 알고리즘 및 신설 노선 운행시간 예측 모델
3 |
--------------------------------------------------------------------------------
/2018_IBUS/data/demand_G.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Namsik-Yoon/Mobility_Project/master/2018_IBUS/data/demand_G.gz
--------------------------------------------------------------------------------
/2018_IBUS/data/new_road_G.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Namsik-Yoon/Mobility_Project/master/2018_IBUS/data/new_road_G.gz
--------------------------------------------------------------------------------
/속도네트워크 구축/excel_정류소현황목록.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Namsik-Yoon/Mobility_Project/master/속도네트워크 구축/excel_정류소현황목록.xlsx
--------------------------------------------------------------------------------
/속도네트워크 구축/노선별 정류장 경유리스트.xls:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Namsik-Yoon/Mobility_Project/master/속도네트워크 구축/노선별 정류장 경유리스트.xls
--------------------------------------------------------------------------------
/2018_IBUS/data/road_network.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Namsik-Yoon/Mobility_Project/master/2018_IBUS/data/road_network.gz
--------------------------------------------------------------------------------
/2018_IBUS/data/정류소현황목록_20190924.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Namsik-Yoon/Mobility_Project/master/2018_IBUS/data/정류소현황목록_20190924.xlsx
--------------------------------------------------------------------------------
/속도네트워크 구축/속도네트워크 구축.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# [Coworked with Jung0Jin in Tactics Lab](https://github.com/Jung0Jin)"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 1,
13 | "metadata": {},
14 | "outputs": [
15 | {
16 | "name": "stdout",
17 | "output_type": "stream",
18 | "text": [
19 | "100% [..........................................................................] 4031488 / 4031488"
20 | ]
21 | },
22 | {
23 | "data": {
24 | "text/plain": [
25 | "'station_sequence_route.xls'"
26 | ]
27 | },
28 | "execution_count": 1,
29 | "metadata": {},
30 | "output_type": "execute_result"
31 | }
32 | ],
33 | "source": [
34 | "# !pip install wget\n",
35 | "import wget\n",
36 | "wget.download('https://www.dropbox.com/s/7pn8swdrje4ei87/BMS_data.txt?dl=1')\n",
37 | "wget.download('https://www.dropbox.com/s/4glojc5ya8h4hwk/excel_station_status.xlsx?dl=1')\n",
38 | "wget.download('https://www.dropbox.com/s/r4cdabs9uopny5z/station_sequence_route.xls?dl=1')"
39 | ]
40 | },
41 | {
42 | "cell_type": "code",
43 | "execution_count": 2,
44 | "metadata": {
45 | "ExecuteTime": {
46 | "end_time": "2020-03-18T08:01:45.680402Z",
47 | "start_time": "2020-03-18T08:01:45.675415Z"
48 | }
49 | },
50 | "outputs": [],
51 | "source": [
52 | "import datetime\n",
53 | "import pandas as pd\n",
54 | "import networkx as nx"
55 | ]
56 | },
57 | {
58 | "cell_type": "code",
59 | "execution_count": 3,
60 | "metadata": {
61 | "ExecuteTime": {
62 | "end_time": "2020-03-18T08:05:46.991153Z",
63 | "start_time": "2020-03-18T08:02:35.427371Z"
64 | },
65 | "scrolled": true
66 | },
67 | "outputs": [
68 | {
69 | "name": "stdout",
70 | "output_type": "stream",
71 | "text": [
72 | "1000000번째 줄\n",
73 | "2000000번째 줄\n",
74 | "3000000번째 줄\n",
75 | "4000000번째 줄\n",
76 | "5000000번째 줄\n",
77 | "6000000번째 줄\n",
78 | "7000000번째 줄\n",
79 | "84023\n"
80 | ]
81 | }
82 | ],
83 | "source": [
84 | "G = {}\n",
85 | "input_file = open('BMS_data.txt','r')\n",
86 | "\n",
87 | "init_line = input_file.readline()\n",
88 | "data_line = input_file.readline()\n",
89 | "data_line = data_line.split(',')\n",
90 | "temp = 0\n",
91 | "while True:\n",
92 | " temp+=1\n",
93 | " if temp%1000000==0:\n",
94 | " print(f'{temp}번째 줄')\n",
95 | " \n",
96 | " source_bus_id = data_line[3]\n",
97 | " source = data_line[4]\n",
98 | " source_time = datetime.datetime.strptime(data_line[5],'%Y%m%d%H%M%S')\n",
99 | " \n",
100 | " data_line = input_file.readline()\n",
101 | " if not data_line:break\n",
102 | " \n",
103 | " data_line = data_line.split(',')\n",
104 | " if data_line == ['']:\n",
105 | " data_line = input_file.readline()\n",
106 | " if not data_line:break\n",
107 | " data_line = data_line.split(',')\n",
108 | " continue\n",
109 | " target_bus_id = data_line[3]\n",
110 | " target = data_line[4]\n",
111 | " target_time = datetime.datetime.strptime(data_line[5],'%Y%m%d%H%M%S')\n",
112 | "\n",
113 | " if source_bus_id == target_bus_id:\n",
114 | " try:\n",
115 | " G[source,target][0]=G[source,target][0]+(target_time-source_time)\n",
116 | " G[source,target][1]+=1\n",
117 | " except KeyError:\n",
118 | " G[source,target] = [target_time-source_time,1]\n",
119 | " \n",
120 | "for key in G:\n",
121 | " G[key] = G[key][0]/G[key][1]\n",
122 | "print(len(G.values()))"
123 | ]
124 | },
125 | {
126 | "cell_type": "code",
127 | "execution_count": 4,
128 | "metadata": {},
129 | "outputs": [
130 | {
131 | "name": "stdout",
132 | "output_type": "stream",
133 | "text": [
134 | "54212\n"
135 | ]
136 | }
137 | ],
138 | "source": [
139 | "## 정류소 간 시간이 0보다 작은 경우 삭제\n",
140 | "\n",
141 | "for key in G.copy():\n",
142 | " if G[key] < datetime.timedelta(0):\n",
143 | " del G[key]\n",
144 | "print(len(G.values()))"
145 | ]
146 | },
147 | {
148 | "cell_type": "code",
149 | "execution_count": 5,
150 | "metadata": {
151 | "scrolled": true
152 | },
153 | "outputs": [
154 | {
155 | "data": {
156 | "text/html": [
157 | "
\n",
158 | "\n",
171 | "
\n",
172 | " \n",
173 | " \n",
174 | " | \n",
175 | " 정류소 번호 | \n",
176 | " 정류소 ID | \n",
177 | " ISC 정류소 ID | \n",
178 | " 위도 | \n",
179 | " 경도 | \n",
180 | "
\n",
181 | " \n",
182 | " \n",
183 | " \n",
184 | " | 0 | \n",
185 | " 37319 | \n",
186 | " 163000319 | \n",
187 | " 2802757 | \n",
188 | " 126.68018830433286 | \n",
189 | " 37.457360395358165 | \n",
190 | "
\n",
191 | " \n",
192 | " | 1 | \n",
193 | " 37326 | \n",
194 | " 163000326 | \n",
195 | " 2802755 | \n",
196 | " 126.67992703811578 | \n",
197 | " 37.45776642315442 | \n",
198 | "
\n",
199 | " \n",
200 | " | 2 | \n",
201 | " 42228 | \n",
202 | " 168000228 | \n",
203 | " 2800619 | \n",
204 | " 126.67339452968905 | \n",
205 | " 37.52184277702059 | \n",
206 | "
\n",
207 | " \n",
208 | " | 3 | \n",
209 | " 40158 | \n",
210 | " 166000158 | \n",
211 | " 2801688 | \n",
212 | " 126.71126751729724 | \n",
213 | " 37.490948333960574 | \n",
214 | "
\n",
215 | " \n",
216 | " | 4 | \n",
217 | " 89146 | \n",
218 | " 168001146 | \n",
219 | " 2806735 | \n",
220 | " 126.61697759175779 | \n",
221 | " 37.559185515339 | \n",
222 | "
\n",
223 | " \n",
224 | "
\n",
225 | "
"
226 | ],
227 | "text/plain": [
228 | " 정류소 번호 정류소 ID ISC 정류소 ID 위도 경도\n",
229 | "0 37319 163000319 2802757 126.68018830433286 37.457360395358165\n",
230 | "1 37326 163000326 2802755 126.67992703811578 37.45776642315442\n",
231 | "2 42228 168000228 2800619 126.67339452968905 37.52184277702059\n",
232 | "3 40158 166000158 2801688 126.71126751729724 37.490948333960574\n",
233 | "4 89146 168001146 2806735 126.61697759175779 37.559185515339"
234 | ]
235 | },
236 | "execution_count": 5,
237 | "metadata": {},
238 | "output_type": "execute_result"
239 | }
240 | ],
241 | "source": [
242 | "stn_status = pd.read_excel('excel_station_status.xlsx',usecols=['정류소 ID','정류소 번호','ISC 정류소 ID','위도','경도'],\n",
243 | " dtype=str)\n",
244 | "stn_status.head()"
245 | ]
246 | },
247 | {
248 | "cell_type": "code",
249 | "execution_count": 14,
250 | "metadata": {},
251 | "outputs": [],
252 | "source": [
253 | "mapping = {stn_status.loc[i,'정류소 ID']:stn_status.loc[i,'ISC 정류소 ID'] for i in stn_status.index}"
254 | ]
255 | },
256 | {
257 | "cell_type": "code",
258 | "execution_count": 15,
259 | "metadata": {},
260 | "outputs": [],
261 | "source": [
262 | "id_list = stn_status['정류소 ID'].tolist()\n",
263 | "isc_id_list = stn_status['ISC 정류소 ID'].tolist()\n",
264 | "for key in G.copy():\n",
265 | " source,target = key\n",
266 | " if (source not in id_list) or (target not in id_list):\n",
267 | " del G[key]\n",
268 | " continue\n",
269 | " source_ = mapping[source]\n",
270 | " target_ = mapping[target]\n",
271 | " \n",
272 | " G[(source_,target_)] = G[key].total_seconds()\n",
273 | " del G[key]"
274 | ]
275 | },
276 | {
277 | "cell_type": "code",
278 | "execution_count": 16,
279 | "metadata": {},
280 | "outputs": [],
281 | "source": [
282 | "networkx_G = nx.DiGraph()\n",
283 | "for key,value in G.items():\n",
284 | " networkx_G.add_edge(*key,time=value)"
285 | ]
286 | },
287 | {
288 | "cell_type": "markdown",
289 | "metadata": {},
290 | "source": [
291 | "확인 및 실험(511번)"
292 | ]
293 | },
294 | {
295 | "cell_type": "code",
296 | "execution_count": 17,
297 | "metadata": {
298 | "scrolled": false
299 | },
300 | "outputs": [
301 | {
302 | "name": "stdout",
303 | "output_type": "stream",
304 | "text": [
305 | "WARNING *** OLE2 inconsistency: SSCS size is 0 but SSAT size is non-zero\n"
306 | ]
307 | },
308 | {
309 | "data": {
310 | "text/html": [
311 | "\n",
312 | "\n",
325 | "
\n",
326 | " \n",
327 | " \n",
328 | " | \n",
329 | " 정류소명 | \n",
330 | " 정류소표준ID | \n",
331 | " 정류소단축ID | \n",
332 | " 노선ID | \n",
333 | " 노선번호 | \n",
334 | " 정류소순번 | \n",
335 | " 버스유형 | \n",
336 | "
\n",
337 | " \n",
338 | " \n",
339 | " \n",
340 | " | 17224 | \n",
341 | " 독배로317번길(삼거리) | \n",
342 | " 163000634 | \n",
343 | " 37634 | \n",
344 | " 165000073 | \n",
345 | " 511 | \n",
346 | " 1 | \n",
347 | " 지선 | \n",
348 | "
\n",
349 | " \n",
350 | " | 17225 | \n",
351 | " SK스카이뷰104동 | \n",
352 | " 163000587 | \n",
353 | " 37587 | \n",
354 | " 165000073 | \n",
355 | " 511 | \n",
356 | " 2 | \n",
357 | " 지선 | \n",
358 | "
\n",
359 | " \n",
360 | " | 17226 | \n",
361 | " SK스카이뷰109동 | \n",
362 | " 163000607 | \n",
363 | " 37607 | \n",
364 | " 165000073 | \n",
365 | " 511 | \n",
366 | " 3 | \n",
367 | " 지선 | \n",
368 | "
\n",
369 | " \n",
370 | " | 17227 | \n",
371 | " 굴다리 | \n",
372 | " 163000142 | \n",
373 | " 37142 | \n",
374 | " 165000073 | \n",
375 | " 511 | \n",
376 | " 4 | \n",
377 | " 지선 | \n",
378 | "
\n",
379 | " \n",
380 | " | 17228 | \n",
381 | " 용현고가교 | \n",
382 | " 163000611 | \n",
383 | " 37611 | \n",
384 | " 165000073 | \n",
385 | " 511 | \n",
386 | " 5 | \n",
387 | " 지선 | \n",
388 | "
\n",
389 | " \n",
390 | " | 17229 | \n",
391 | " 인하대후문 | \n",
392 | " 163000165 | \n",
393 | " 37165 | \n",
394 | " 165000073 | \n",
395 | " 511 | \n",
396 | " 6 | \n",
397 | " 지선 | \n",
398 | "
\n",
399 | " \n",
400 | " | 17230 | \n",
401 | " 정석항공과학고 | \n",
402 | " 163000168 | \n",
403 | " 37168 | \n",
404 | " 165000073 | \n",
405 | " 511 | \n",
406 | " 7 | \n",
407 | " 지선 | \n",
408 | "
\n",
409 | " \n",
410 | " | 17231 | \n",
411 | " 학산소극장 | \n",
412 | " 163000169 | \n",
413 | " 37169 | \n",
414 | " 165000073 | \n",
415 | " 511 | \n",
416 | " 8 | \n",
417 | " 지선 | \n",
418 | "
\n",
419 | " \n",
420 | " | 17232 | \n",
421 | " 용남파출소 | \n",
422 | " 163000177 | \n",
423 | " 37177 | \n",
424 | " 165000073 | \n",
425 | " 511 | \n",
426 | " 9 | \n",
427 | " 지선 | \n",
428 | "
\n",
429 | " \n",
430 | " | 17233 | \n",
431 | " 용일사거리 | \n",
432 | " 163000208 | \n",
433 | " 37208 | \n",
434 | " 165000073 | \n",
435 | " 511 | \n",
436 | " 10 | \n",
437 | " 지선 | \n",
438 | "
\n",
439 | " \n",
440 | " | 17234 | \n",
441 | " 인천기계공고 | \n",
442 | " 163000272 | \n",
443 | " 37272 | \n",
444 | " 165000073 | \n",
445 | " 511 | \n",
446 | " 11 | \n",
447 | " 지선 | \n",
448 | "
\n",
449 | " \n",
450 | " | 17235 | \n",
451 | " 주안2동치안센터 | \n",
452 | " 163000302 | \n",
453 | " 37302 | \n",
454 | " 165000073 | \n",
455 | " 511 | \n",
456 | " 12 | \n",
457 | " 지선 | \n",
458 | "
\n",
459 | " \n",
460 | " | 17236 | \n",
461 | " 제일시장 | \n",
462 | " 163000316 | \n",
463 | " 37316 | \n",
464 | " 165000073 | \n",
465 | " 511 | \n",
466 | " 13 | \n",
467 | " 지선 | \n",
468 | "
\n",
469 | " \n",
470 | " | 17237 | \n",
471 | " 주안사거리 | \n",
472 | " 163000514 | \n",
473 | " 37514 | \n",
474 | " 165000073 | \n",
475 | " 511 | \n",
476 | " 14 | \n",
477 | " 지선 | \n",
478 | "
\n",
479 | " \n",
480 | " | 17238 | \n",
481 | " 교보생명 | \n",
482 | " 163000357 | \n",
483 | " 37357 | \n",
484 | " 165000073 | \n",
485 | " 511 | \n",
486 | " 15 | \n",
487 | " 지선 | \n",
488 | "
\n",
489 | " \n",
490 | " | 17239 | \n",
491 | " 주안역환승정류장 | \n",
492 | " 163000617 | \n",
493 | " 37617 | \n",
494 | " 165000073 | \n",
495 | " 511 | \n",
496 | " 16 | \n",
497 | " 지선 | \n",
498 | "
\n",
499 | " \n",
500 | " | 17240 | \n",
501 | " 주안1동행정복지센터 | \n",
502 | " 163000385 | \n",
503 | " 37385 | \n",
504 | " 165000073 | \n",
505 | " 511 | \n",
506 | " 17 | \n",
507 | " 지선 | \n",
508 | "
\n",
509 | " \n",
510 | " | 17241 | \n",
511 | " 도화IC | \n",
512 | " 163000356 | \n",
513 | " 37356 | \n",
514 | " 165000073 | \n",
515 | " 511 | \n",
516 | " 18 | \n",
517 | " 지선 | \n",
518 | "
\n",
519 | " \n",
520 | " | 17242 | \n",
521 | " 롯데월드타워 | \n",
522 | " 163000325 | \n",
523 | " 37325 | \n",
524 | " 165000073 | \n",
525 | " 511 | \n",
526 | " 19 | \n",
527 | " 지선 | \n",
528 | "
\n",
529 | " \n",
530 | " | 17243 | \n",
531 | " 인천기계공고 | \n",
532 | " 163000537 | \n",
533 | " 37537 | \n",
534 | " 165000073 | \n",
535 | " 511 | \n",
536 | " 20 | \n",
537 | " 지선 | \n",
538 | "
\n",
539 | " \n",
540 | " | 17244 | \n",
541 | " 인천기계공고 | \n",
542 | " 163000281 | \n",
543 | " 37281 | \n",
544 | " 165000073 | \n",
545 | " 511 | \n",
546 | " 21 | \n",
547 | " 지선 | \n",
548 | "
\n",
549 | " \n",
550 | " | 17245 | \n",
551 | " 용일사거리 | \n",
552 | " 163000218 | \n",
553 | " 37218 | \n",
554 | " 165000073 | \n",
555 | " 511 | \n",
556 | " 22 | \n",
557 | " 지선 | \n",
558 | "
\n",
559 | " \n",
560 | " | 17246 | \n",
561 | " 용남파출소 | \n",
562 | " 163000184 | \n",
563 | " 37184 | \n",
564 | " 165000073 | \n",
565 | " 511 | \n",
566 | " 23 | \n",
567 | " 지선 | \n",
568 | "
\n",
569 | " \n",
570 | " | 17247 | \n",
571 | " 학산소극장 | \n",
572 | " 163000173 | \n",
573 | " 37173 | \n",
574 | " 165000073 | \n",
575 | " 511 | \n",
576 | " 24 | \n",
577 | " 지선 | \n",
578 | "
\n",
579 | " \n",
580 | " | 17248 | \n",
581 | " 정석항공과학고 | \n",
582 | " 163000170 | \n",
583 | " 37170 | \n",
584 | " 165000073 | \n",
585 | " 511 | \n",
586 | " 25 | \n",
587 | " 지선 | \n",
588 | "
\n",
589 | " \n",
590 | " | 17249 | \n",
591 | " 인하대후문 | \n",
592 | " 163000167 | \n",
593 | " 37167 | \n",
594 | " 165000073 | \n",
595 | " 511 | \n",
596 | " 26 | \n",
597 | " 지선 | \n",
598 | "
\n",
599 | " \n",
600 | " | 17250 | \n",
601 | " 용현고가교 | \n",
602 | " 163000550 | \n",
603 | " 37550 | \n",
604 | " 165000073 | \n",
605 | " 511 | \n",
606 | " 27 | \n",
607 | " 지선 | \n",
608 | "
\n",
609 | " \n",
610 | " | 17251 | \n",
611 | " 인하대역3번출구 | \n",
612 | " 163000127 | \n",
613 | " 37127 | \n",
614 | " 165000073 | \n",
615 | " 511 | \n",
616 | " 28 | \n",
617 | " 지선 | \n",
618 | "
\n",
619 | " \n",
620 | " | 17252 | \n",
621 | " 인하대역 | \n",
622 | " 163000596 | \n",
623 | " 37596 | \n",
624 | " 165000073 | \n",
625 | " 511 | \n",
626 | " 29 | \n",
627 | " 지선 | \n",
628 | "
\n",
629 | " \n",
630 | " | 17253 | \n",
631 | " SK스카이뷰 | \n",
632 | " 163000601 | \n",
633 | " 37601 | \n",
634 | " 165000073 | \n",
635 | " 511 | \n",
636 | " 30 | \n",
637 | " 지선 | \n",
638 | "
\n",
639 | " \n",
640 | "
\n",
641 | "
"
642 | ],
643 | "text/plain": [
644 | " 정류소명 정류소표준ID 정류소단축ID 노선ID 노선번호 정류소순번 버스유형\n",
645 | "17224 독배로317번길(삼거리) 163000634 37634 165000073 511 1 지선\n",
646 | "17225 SK스카이뷰104동 163000587 37587 165000073 511 2 지선\n",
647 | "17226 SK스카이뷰109동 163000607 37607 165000073 511 3 지선\n",
648 | "17227 굴다리 163000142 37142 165000073 511 4 지선\n",
649 | "17228 용현고가교 163000611 37611 165000073 511 5 지선\n",
650 | "17229 인하대후문 163000165 37165 165000073 511 6 지선\n",
651 | "17230 정석항공과학고 163000168 37168 165000073 511 7 지선\n",
652 | "17231 학산소극장 163000169 37169 165000073 511 8 지선\n",
653 | "17232 용남파출소 163000177 37177 165000073 511 9 지선\n",
654 | "17233 용일사거리 163000208 37208 165000073 511 10 지선\n",
655 | "17234 인천기계공고 163000272 37272 165000073 511 11 지선\n",
656 | "17235 주안2동치안센터 163000302 37302 165000073 511 12 지선\n",
657 | "17236 제일시장 163000316 37316 165000073 511 13 지선\n",
658 | "17237 주안사거리 163000514 37514 165000073 511 14 지선\n",
659 | "17238 교보생명 163000357 37357 165000073 511 15 지선\n",
660 | "17239 주안역환승정류장 163000617 37617 165000073 511 16 지선\n",
661 | "17240 주안1동행정복지센터 163000385 37385 165000073 511 17 지선\n",
662 | "17241 도화IC 163000356 37356 165000073 511 18 지선\n",
663 | "17242 롯데월드타워 163000325 37325 165000073 511 19 지선\n",
664 | "17243 인천기계공고 163000537 37537 165000073 511 20 지선\n",
665 | "17244 인천기계공고 163000281 37281 165000073 511 21 지선\n",
666 | "17245 용일사거리 163000218 37218 165000073 511 22 지선\n",
667 | "17246 용남파출소 163000184 37184 165000073 511 23 지선\n",
668 | "17247 학산소극장 163000173 37173 165000073 511 24 지선\n",
669 | "17248 정석항공과학고 163000170 37170 165000073 511 25 지선\n",
670 | "17249 인하대후문 163000167 37167 165000073 511 26 지선\n",
671 | "17250 용현고가교 163000550 37550 165000073 511 27 지선\n",
672 | "17251 인하대역3번출구 163000127 37127 165000073 511 28 지선\n",
673 | "17252 인하대역 163000596 37596 165000073 511 29 지선\n",
674 | "17253 SK스카이뷰 163000601 37601 165000073 511 30 지선"
675 | ]
676 | },
677 | "execution_count": 17,
678 | "metadata": {},
679 | "output_type": "execute_result"
680 | }
681 | ],
682 | "source": [
683 | "route_sequence = pd.read_excel('station_sequence_route.xls',dtype=str)\n",
684 | "sequence_511 = route_sequence[route_sequence['노선번호']=='511']\n",
685 | "sequence_511"
686 | ]
687 | },
688 | {
689 | "cell_type": "code",
690 | "execution_count": 18,
691 | "metadata": {
692 | "scrolled": true
693 | },
694 | "outputs": [
695 | {
696 | "name": "stderr",
697 | "output_type": "stream",
698 | "text": [
699 | "C:\\Users\\skatl\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\ipykernel_launcher.py:1: SettingWithCopyWarning: \n",
700 | "A value is trying to be set on a copy of a slice from a DataFrame.\n",
701 | "Try using .loc[row_indexer,col_indexer] = value instead\n",
702 | "\n",
703 | "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
704 | " \"\"\"Entry point for launching an IPython kernel.\n",
705 | "C:\\Users\\skatl\\AppData\\Local\\Continuum\\anaconda3\\lib\\site-packages\\ipykernel_launcher.py:5: SettingWithCopyWarning: \n",
706 | "A value is trying to be set on a copy of a slice from a DataFrame\n",
707 | "\n",
708 | "See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n",
709 | " \"\"\"\n"
710 | ]
711 | },
712 | {
713 | "data": {
714 | "text/plain": [
715 | "['2807441',\n",
716 | " '2806808',\n",
717 | " '2806914',\n",
718 | " '2802920',\n",
719 | " '2807167',\n",
720 | " '2802898',\n",
721 | " '2802895',\n",
722 | " '2802894',\n",
723 | " '2802887',\n",
724 | " '2802862',\n",
725 | " '2802803',\n",
726 | " '2802774',\n",
727 | " '2802760',\n",
728 | " '2802617',\n",
729 | " '2802733',\n",
730 | " '2807110',\n",
731 | " '2802710',\n",
732 | " '2802734',\n",
733 | " '2802756',\n",
734 | " '2805155',\n",
735 | " '2802794',\n",
736 | " '2802852',\n",
737 | " '2802880',\n",
738 | " '2802890',\n",
739 | " '2802893',\n",
740 | " '2802896',\n",
741 | " '2805500',\n",
742 | " '2802934',\n",
743 | " '2806811',\n",
744 | " '2806809']"
745 | ]
746 | },
747 | "execution_count": 18,
748 | "metadata": {},
749 | "output_type": "execute_result"
750 | }
751 | ],
752 | "source": [
753 | "sequence_511['ISC 정류소 ID'] = None\n",
754 | "for idx in sequence_511.index:\n",
755 | " id = sequence_511.loc[idx,'정류소표준ID']\n",
756 | " isc_id = mapping[id]\n",
757 | " sequence_511.loc[idx,'ISC 정류소 ID'] = isc_id\n",
758 | "sequence_511_isc = sequence_511['ISC 정류소 ID'].tolist()\n",
759 | "sequence_511_isc"
760 | ]
761 | },
762 | {
763 | "cell_type": "code",
764 | "execution_count": 19,
765 | "metadata": {},
766 | "outputs": [
767 | {
768 | "ename": "ZeroDivisionError",
769 | "evalue": "division by zero",
770 | "output_type": "error",
771 | "traceback": [
772 | "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
773 | "\u001b[1;31mZeroDivisionError\u001b[0m Traceback (most recent call last)",
774 | "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0mtotal_time\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mavg_time\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0msum\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlist\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mG\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvalues\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m/\u001b[0m\u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlist\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mG\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvalues\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 3\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0msource\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mtarget\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mzip\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msequence_511_isc\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0msequence_511_isc\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mtarget\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0msequence_511_isc\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m-\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;32mbreak\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
775 | "\u001b[1;31mZeroDivisionError\u001b[0m: division by zero"
776 | ]
777 | }
778 | ],
779 | "source": [
780 | "total_time = 0\n",
781 | "avg_time = sum(list(G.values()))/len(list(G.values()))\n",
782 | "for source,target in zip(sequence_511_isc[:-1],sequence_511_isc[1:]):\n",
783 | " if target == sequence_511_isc[-1]:break\n",
784 | " try:\n",
785 | " time = networkx_G.edges[(source,target)]['time']\n",
786 | " except KeyError:\n",
787 | " time = avg_time\n",
788 | " total_time+=time\n",
789 | "print(total_time)"
790 | ]
791 | },
792 | {
793 | "cell_type": "code",
794 | "execution_count": null,
795 | "metadata": {},
796 | "outputs": [],
797 | "source": [
798 | "total_time"
799 | ]
800 | },
801 | {
802 | "cell_type": "code",
803 | "execution_count": null,
804 | "metadata": {},
805 | "outputs": [],
806 | "source": []
807 | }
808 | ],
809 | "metadata": {
810 | "hide_input": false,
811 | "kernelspec": {
812 | "display_name": "Python 3",
813 | "language": "python",
814 | "name": "python3"
815 | },
816 | "language_info": {
817 | "codemirror_mode": {
818 | "name": "ipython",
819 | "version": 3
820 | },
821 | "file_extension": ".py",
822 | "mimetype": "text/x-python",
823 | "name": "python",
824 | "nbconvert_exporter": "python",
825 | "pygments_lexer": "ipython3",
826 | "version": "3.7.4"
827 | },
828 | "toc": {
829 | "base_numbering": 1,
830 | "nav_menu": {},
831 | "number_sections": true,
832 | "sideBar": true,
833 | "skip_h1_title": false,
834 | "title_cell": "Table of Contents",
835 | "title_sidebar": "Contents",
836 | "toc_cell": false,
837 | "toc_position": {},
838 | "toc_section_display": true,
839 | "toc_window_display": false
840 | },
841 | "varInspector": {
842 | "cols": {
843 | "lenName": 16,
844 | "lenType": 16,
845 | "lenVar": 40
846 | },
847 | "kernels_config": {
848 | "python": {
849 | "delete_cmd_postfix": "",
850 | "delete_cmd_prefix": "del ",
851 | "library": "var_list.py",
852 | "varRefreshCmd": "print(var_dic_list())"
853 | },
854 | "r": {
855 | "delete_cmd_postfix": ") ",
856 | "delete_cmd_prefix": "rm(",
857 | "library": "var_list.r",
858 | "varRefreshCmd": "cat(var_dic_list()) "
859 | }
860 | },
861 | "types_to_exclude": [
862 | "module",
863 | "function",
864 | "builtin_function_or_method",
865 | "instance",
866 | "_Feature"
867 | ],
868 | "window_display": false
869 | }
870 | },
871 | "nbformat": 4,
872 | "nbformat_minor": 4
873 | }
874 |
--------------------------------------------------------------------------------
/속도네트워크 구축/BMS 데이터를 이용한 노선도 및 노선운행시간 예측.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "import pandas as pd\n",
10 | "from tqdm import tqdm\n",
11 | "import numpy as np\n",
12 | "import networkx as nx\n",
13 | "from math import radians, cos, sin, asin, sqrt\n",
14 | "use_cols = ['ROUTE_NAME','F_STTN_ID','F_STTN_ISC_ID','T_STTN_ID','T_STTN_ISC_ID','TRANSIT_TIME','STOP_SEQ']"
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": 2,
20 | "metadata": {},
21 | "outputs": [],
22 | "source": [
23 | "\"\"\"위경도 거리계산 함수\"\"\"\n",
24 | "\"\"\"\n",
25 | "신규,변경 노선의 경우, 경유 정류장 간 bms데이터가 없는 경우가 생길 수 있음\n",
26 | "따라서 정류장간 거리를 구한 후, 시내버스 평균속도(현재 15로 산정)를 나누어 정류장간 통행시간을 산출 \n",
27 | "\"\"\"\n",
28 | "def haversine(lon1, lat1, lon2, lat2):\n",
29 | " \"\"\"\n",
30 | " Calculate the great circle distance between two points \n",
31 | " on the earth (specified in decimal degrees)\n",
32 | " \"\"\"\n",
33 | " # convert decimal degrees to radians \n",
34 | " lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])\n",
35 | " # haversine formula \n",
36 | " dlon = lon2 - lon1 \n",
37 | " dlat = lat2 - lat1 \n",
38 | " a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2\n",
39 | " c = 2 * asin(sqrt(a)) \n",
40 | " # Radius of earth in kilometers is 6371\n",
41 | " km = 6371* c\n",
42 | " return km"
43 | ]
44 | },
45 | {
46 | "cell_type": "code",
47 | "execution_count": 3,
48 | "metadata": {
49 | "scrolled": true
50 | },
51 | "outputs": [
52 | {
53 | "data": {
54 | "text/html": [
55 | "\n",
56 | "\n",
69 | "
\n",
70 | " \n",
71 | " \n",
72 | " | \n",
73 | " Sttn Id | \n",
74 | " Sttn Isc Id | \n",
75 | " Sttn Name | \n",
76 | " Sttn Lat | \n",
77 | " Sttn Lon | \n",
78 | "
\n",
79 | " \n",
80 | " \n",
81 | " \n",
82 | " | 0 | \n",
83 | " 232000077 | \n",
84 | " 2800001 | \n",
85 | " 양도마을.대림아파트 | \n",
86 | " 37.604731898 | \n",
87 | " 126.722346797 | \n",
88 | "
\n",
89 | " \n",
90 | " | 1 | \n",
91 | " 232000076 | \n",
92 | " 2800002 | \n",
93 | " 양도마을.대림아파트 | \n",
94 | " 37.604322917 | \n",
95 | " 126.722033457 | \n",
96 | "
\n",
97 | " \n",
98 | " | 2 | \n",
99 | " 232000075 | \n",
100 | " 2800003 | \n",
101 | " 수행마을 | \n",
102 | " 37.607893558 | \n",
103 | " 126.723575258 | \n",
104 | "
\n",
105 | " \n",
106 | " | 3 | \n",
107 | " 232000074 | \n",
108 | " 2800004 | \n",
109 | " 수행마을 | \n",
110 | " 37.607893308 | \n",
111 | " 126.723216093 | \n",
112 | "
\n",
113 | " \n",
114 | " | 4 | \n",
115 | " 232000073 | \n",
116 | " 2800005 | \n",
117 | " 유현마을.신동아아파트 | \n",
118 | " 37.59642183 | \n",
119 | " 126.721286176 | \n",
120 | "
\n",
121 | " \n",
122 | "
\n",
123 | "
"
124 | ],
125 | "text/plain": [
126 | " Sttn Id Sttn Isc Id Sttn Name Sttn Lat Sttn Lon\n",
127 | "0 232000077 2800001 양도마을.대림아파트 37.604731898 126.722346797\n",
128 | "1 232000076 2800002 양도마을.대림아파트 37.604322917 126.722033457\n",
129 | "2 232000075 2800003 수행마을 37.607893558 126.723575258\n",
130 | "3 232000074 2800004 수행마을 37.607893308 126.723216093\n",
131 | "4 232000073 2800005 유현마을.신동아아파트 37.59642183 126.721286176"
132 | ]
133 | },
134 | "execution_count": 3,
135 | "metadata": {},
136 | "output_type": "execute_result"
137 | }
138 | ],
139 | "source": [
140 | "\"\"\"정류장 정보 dataframe\"\"\"\n",
141 | "stn_status = pd.read_excel('20200806_V12_경유정류장순서_서민호(200810.v1.김민기).xlsx',\n",
142 | " sheet_name='정류장위치',dtype=str)\n",
143 | "stn_status.head()"
144 | ]
145 | },
146 | {
147 | "cell_type": "code",
148 | "execution_count": 4,
149 | "metadata": {},
150 | "outputs": [
151 | {
152 | "data": {
153 | "text/html": [
154 | "\n",
155 | "\n",
168 | "
\n",
169 | " \n",
170 | " \n",
171 | " | \n",
172 | " 정류소 명 | \n",
173 | " 정류소 ID | \n",
174 | " ISC 정류소 ID | \n",
175 | " 위도 | \n",
176 | " 경도 | \n",
177 | "
\n",
178 | " \n",
179 | " \n",
180 | " \n",
181 | " | 0 | \n",
182 | " (구)시민회관사거리 | \n",
183 | " 163000319 | \n",
184 | " 2802757 | \n",
185 | " 126.68018830433286 | \n",
186 | " 37.457360395358165 | \n",
187 | "
\n",
188 | " \n",
189 | " | 1 | \n",
190 | " (구)시민회관사거리 | \n",
191 | " 163000326 | \n",
192 | " 2802755 | \n",
193 | " 126.67992703811578 | \n",
194 | " 37.45776642315442 | \n",
195 | "
\n",
196 | " \n",
197 | " | 2 | \n",
198 | " (구)신현주공 | \n",
199 | " 168000228 | \n",
200 | " 2800619 | \n",
201 | " 126.67339452968905 | \n",
202 | " 37.52184277702059 | \n",
203 | "
\n",
204 | " \n",
205 | " | 3 | \n",
206 | " (구)현대백화점 | \n",
207 | " 166000158 | \n",
208 | " 2801688 | \n",
209 | " 126.71126751729724 | \n",
210 | " 37.490948333960574 | \n",
211 | "
\n",
212 | " \n",
213 | " | 4 | \n",
214 | " (주)경동세라믹스 | \n",
215 | " 168001146 | \n",
216 | " 2806735 | \n",
217 | " 126.61697759175779 | \n",
218 | " 37.559185515339 | \n",
219 | "
\n",
220 | " \n",
221 | "
\n",
222 | "
"
223 | ],
224 | "text/plain": [
225 | " 정류소 명 정류소 ID ISC 정류소 ID 위도 경도\n",
226 | "0 (구)시민회관사거리 163000319 2802757 126.68018830433286 37.457360395358165\n",
227 | "1 (구)시민회관사거리 163000326 2802755 126.67992703811578 37.45776642315442\n",
228 | "2 (구)신현주공 168000228 2800619 126.67339452968905 37.52184277702059\n",
229 | "3 (구)현대백화점 166000158 2801688 126.71126751729724 37.490948333960574\n",
230 | "4 (주)경동세라믹스 168001146 2806735 126.61697759175779 37.559185515339"
231 | ]
232 | },
233 | "execution_count": 4,
234 | "metadata": {},
235 | "output_type": "execute_result"
236 | }
237 | ],
238 | "source": [
239 | "stn_status2 = pd.read_excel('excel_station_status.xlsx',dtype=str,\n",
240 | " usecols=['정류소 명','정류소 ID','ISC 정류소 ID','위도','경도'])\n",
241 | "stn_status2.head()"
242 | ]
243 | },
244 | {
245 | "cell_type": "code",
246 | "execution_count": 5,
247 | "metadata": {},
248 | "outputs": [],
249 | "source": [
250 | "\"\"\"정류장 정보 검색 함수\"\"\"\n",
251 | "def find_stn_status(id_):\n",
252 | " \"\"\"\n",
253 | " id를 넣으면 [정류장명, 위도, 경도] 값을 return\n",
254 | " \"\"\"\n",
255 | " try:\n",
256 | " if len(id_)==7:\n",
257 | " return stn_status[stn_status['Sttn Isc Id']==id_][['Sttn Name','Sttn Lon','Sttn Lat']].values[0]\n",
258 | " return stn_status[stn_status['Sttn Id']==id_][['Sttn Name','Sttn Lon','Sttn Lat']].values[0]\n",
259 | " except IndexError:\n",
260 | " if len(id_)==7:\n",
261 | " return stn_status2[stn_status2['ISC 정류소 ID']==id_][['정류소 명','위도','경도']].values[0]\n",
262 | " return stn_status2[stn_status2['정류소 ID']==id_][['정류소 명','위도','경도']].values[0]"
263 | ]
264 | },
265 | {
266 | "cell_type": "code",
267 | "execution_count": 6,
268 | "metadata": {},
269 | "outputs": [
270 | {
271 | "data": {
272 | "text/html": [
273 | "\n",
274 | "\n",
287 | "
\n",
288 | " \n",
289 | " \n",
290 | " | \n",
291 | " ROUTE_NAME | \n",
292 | " F_STTN_ID | \n",
293 | " F_STTN_ISC_ID | \n",
294 | " T_STTN_ID | \n",
295 | " T_STTN_ISC_ID | \n",
296 | " STOP_SEQ | \n",
297 | " TRANSIT_TIME | \n",
298 | "
\n",
299 | " \n",
300 | " \n",
301 | " \n",
302 | " | 0 | \n",
303 | " 12 | \n",
304 | " 168000066 | \n",
305 | " 2800760 | \n",
306 | " 168000085 | \n",
307 | " 2800741 | \n",
308 | " 34 | \n",
309 | " 32.0 | \n",
310 | "
\n",
311 | " \n",
312 | " | 1 | \n",
313 | " 12 | \n",
314 | " 168000085 | \n",
315 | " 2800741 | \n",
316 | " 168000101 | \n",
317 | " 2800725 | \n",
318 | " 35 | \n",
319 | " 40.0 | \n",
320 | "
\n",
321 | " \n",
322 | " | 2 | \n",
323 | " 12 | \n",
324 | " 168000101 | \n",
325 | " 2800725 | \n",
326 | " 168000136 | \n",
327 | " 2800691 | \n",
328 | " 36 | \n",
329 | " 186.0 | \n",
330 | "
\n",
331 | " \n",
332 | " | 3 | \n",
333 | " 12 | \n",
334 | " 168000136 | \n",
335 | " 2800691 | \n",
336 | " 168000143 | \n",
337 | " 2800684 | \n",
338 | " 37 | \n",
339 | " 48.0 | \n",
340 | "
\n",
341 | " \n",
342 | " | 4 | \n",
343 | " 12 | \n",
344 | " 168000143 | \n",
345 | " 2800684 | \n",
346 | " 168000151 | \n",
347 | " 2800676 | \n",
348 | " 38 | \n",
349 | " 119.0 | \n",
350 | "
\n",
351 | " \n",
352 | "
\n",
353 | "
"
354 | ],
355 | "text/plain": [
356 | " ROUTE_NAME F_STTN_ID F_STTN_ISC_ID T_STTN_ID T_STTN_ISC_ID STOP_SEQ \\\n",
357 | "0 12 168000066 2800760 168000085 2800741 34 \n",
358 | "1 12 168000085 2800741 168000101 2800725 35 \n",
359 | "2 12 168000101 2800725 168000136 2800691 36 \n",
360 | "3 12 168000136 2800691 168000143 2800684 37 \n",
361 | "4 12 168000143 2800684 168000151 2800676 38 \n",
362 | "\n",
363 | " TRANSIT_TIME \n",
364 | "0 32.0 \n",
365 | "1 40.0 \n",
366 | "2 186.0 \n",
367 | "3 48.0 \n",
368 | "4 119.0 "
369 | ]
370 | },
371 | "execution_count": 6,
372 | "metadata": {},
373 | "output_type": "execute_result"
374 | }
375 | ],
376 | "source": [
377 | "\"\"\"bms data load 및 negative, zero value 제거\"\"\"\n",
378 | "bms_data = pd.read_csv('BMSdata_20200731_윤남식V2.csv',dtype=str,usecols=use_cols)\n",
379 | "negative_idx = bms_data[bms_data['TRANSIT_TIME'].astype(float)<=0].index\n",
380 | "bms_data.drop(negative_idx,inplace=True)\n",
381 | "bms_data.head()"
382 | ]
383 | },
384 | {
385 | "cell_type": "code",
386 | "execution_count": 7,
387 | "metadata": {},
388 | "outputs": [
389 | {
390 | "data": {
391 | "text/html": [
392 | "\n",
393 | "\n",
406 | "
\n",
407 | " \n",
408 | " \n",
409 | " | \n",
410 | " 노선번호 | \n",
411 | " 운행시간 | \n",
412 | "
\n",
413 | " \n",
414 | " \n",
415 | " \n",
416 | " | 0 | \n",
417 | " 117 | \n",
418 | " 105 | \n",
419 | "
\n",
420 | " \n",
421 | " | 1 | \n",
422 | " 10 | \n",
423 | " 216 | \n",
424 | "
\n",
425 | " \n",
426 | " | 2 | \n",
427 | " 103 | \n",
428 | " 276 | \n",
429 | "
\n",
430 | " \n",
431 | " | 3 | \n",
432 | " 111 | \n",
433 | " 275 | \n",
434 | "
\n",
435 | " \n",
436 | " | 4 | \n",
437 | " 112 | \n",
438 | " 265 | \n",
439 | "
\n",
440 | " \n",
441 | "
\n",
442 | "
"
443 | ],
444 | "text/plain": [
445 | " 노선번호 운행시간\n",
446 | "0 117 105\n",
447 | "1 10 216\n",
448 | "2 103 276\n",
449 | "3 111 275\n",
450 | "4 112 265"
451 | ]
452 | },
453 | "execution_count": 7,
454 | "metadata": {},
455 | "output_type": "execute_result"
456 | }
457 | ],
458 | "source": [
459 | "\"\"\"존치된 노선들의 노선명과 시에서 인가한 운행시간\"\"\"\n",
460 | "existed_routes_df = pd.read_excel('존치노선.xlsx',dtype=str)\n",
461 | "existed_routes_df.head()"
462 | ]
463 | },
464 | {
465 | "cell_type": "code",
466 | "execution_count": 8,
467 | "metadata": {},
468 | "outputs": [
469 | {
470 | "name": "stdout",
471 | "output_type": "stream",
472 | "text": [
473 | "bms에 찍히지않은 노선 : 598-1\n"
474 | ]
475 | }
476 | ],
477 | "source": [
478 | "\"\"\" 존치노선들의 노선명이 bms_data에 존재하는지 확인 \"\"\"\n",
479 | "\"\"\" bms_data에 들어있는 nan 노선명이 598-1이 아닐까 추측하였으나, \"\"\"\n",
480 | "\"\"\" 아니고 7,43,72번 중 하나의 노선임(bms애 3개 노선전부 찍히긴함) \"\"\"\n",
481 | "\"\"\" ----------------------------------------------------------- \"\"\"\n",
482 | "bms_route_name = bms_data['ROUTE_NAME'].unique()\n",
483 | "for route_name in existed_routes_df['노선번호']:\n",
484 | " if route_name not in bms_route_name:\n",
485 | " print('bms에 찍히지않은 노선 : ',route_name)"
486 | ]
487 | },
488 | {
489 | "cell_type": "markdown",
490 | "metadata": {},
491 | "source": [
492 | "# 117번노선을 예시로 bms_data_df로 노선추출 \n",
493 | "\n",
494 | "```\n",
495 | "\n",
496 | "issue 1) 정해진 노선대로 다니지않고, 임의의 정류장이 to_station에 찍힘 \n",
497 | "ex) 노선도가 a-b-c-d 일때, (a,b) 및 (a,c)가 존재\n",
498 | "sol fail) F-T를 tree 구조로 변환하여 max_depth를 구하여 노선도를 복원 -> cyclic 구조로인해 불가 \n",
499 | "위 예시 a-b-c-d 중 (d,a)가 존재\n",
500 | "sol clear) bms_data에서 STOP_SEQ 순서대로 출발 정류장ID를 나열\n",
501 | "\n",
502 | "==================================================================\n",
503 | "==================================================================\n",
504 | "\n",
505 | "issue 2) i번째 to stn이 i+1번째 from stn이 되지않는경우가 존재(버스가 정차하지않고 지나간것으로 추정)\n",
506 | "\n",
507 | "ex) 117번 노선의 stop_seq의 내림차순한 결과 ***가 해당\n",
508 | "LH7단지 - 센트럴푸르지오자이 - 한양수자인(옆문) - 우미린2단지 정문 - ... - 우미린1단지후문 - 영종KCC스위첸옆문 - 인천공항TG(미정차) - 개화역 - 인천공항TG(미정차) - 영종KCC스위첸옆문 - 우미린1단지후문 (네이버맵 기준)\n",
509 | "\n",
510 | "['T id' 'T isc id''F id' 'F isc id']\n",
511 | "['161000452' '2805694' '161000660' '2805636'] *** (LH7단지, 센트럴푸르지오자이)\n",
512 | "['161000510' '2806053' '161000513' '2806032'] (한양수자인(옆문),우미린2단지정문) \n",
513 | "['161000513' '2806032' '161000455' '2806025']\n",
514 | "['161000455' '2806025' '161000488' '2805697']\n",
515 | "['161000488' '2805697' '161000457' '2805699']\n",
516 | "['161000457' '2805699' '161000459' '2805701']\n",
517 | "['161000459' '2805701' '161000651' '2807440']\n",
518 | "['161000651' '2807440' '161000583' '2806806']\n",
519 | "['161000583' '2806806' '161000462' '2805704'] (우미린1단지정문, 우미린1단지후문)\n",
520 | "['161000462' '2805704' '161000756' '2807625'] *** (우미린1단지후문, 영종KCC스위첸옆문)\n",
521 | "['168000690' '2807549' '168000691' '2807548'] *** (인천공항TG(미정차), 인천공항TG(미정차))\n",
522 | "['115000182' '2806228' '168000691' '2807548'] *** (개화역, 인천공항TG(미정차))\n",
523 | "['168000691' '2807548' '161000755' '2807626'] *** (인천공항TG(미정차), 영종KCC스위첸옆문)\n",
524 | "['161000461' '2805703' '161000584' '2806807'] (우미린1단지후문, 우미린1단지정문)\n",
525 | "['161000584' '2806807' '161000650' '2807439']\n",
526 | "['161000650' '2807439' '161000460' '2805702']\n",
527 | "['161000460' '2805702' '161000458' '2805700']\n",
528 | "['161000458' '2805700' '161000489' '2805698']\n",
529 | "['161000489' '2805698' '161000456' '2806024']\n",
530 | "['161000456' '2806024' '161000512' '2806031']\n",
531 | "['161000512' '2806031' '161000537' '2806083']\n",
532 | "['161000537' '2806083' '161000661' '2805637'] (한양수자인(옆문),센트럴푸르지오자이)\n",
533 | "\n",
534 | "sol fail) i+1번째 row 삭제? -> 네이버맵 기준으로 노선도를 볼때 삭제하면 안됨\n",
535 | "sol clear) i번째 row의 to를 from으로, i+1번째 row의 from을 to로 하는 row를 삽입\n",
536 | "\n",
537 | "```"
538 | ]
539 | },
540 | {
541 | "cell_type": "code",
542 | "execution_count": 9,
543 | "metadata": {},
544 | "outputs": [
545 | {
546 | "data": {
547 | "text/html": [
548 | "\n",
549 | "\n",
562 | "
\n",
563 | " \n",
564 | " \n",
565 | " | \n",
566 | " ROUTE_NAME | \n",
567 | " F_STTN_ID | \n",
568 | " F_STTN_ISC_ID | \n",
569 | " T_STTN_ID | \n",
570 | " T_STTN_ISC_ID | \n",
571 | " STOP_SEQ | \n",
572 | " TRANSIT_TIME | \n",
573 | "
\n",
574 | " \n",
575 | " \n",
576 | " \n",
577 | " | 1626690 | \n",
578 | " 117 | \n",
579 | " 168000690 | \n",
580 | " 2807549 | \n",
581 | " 168000691 | \n",
582 | " 2807548 | \n",
583 | " 11 | \n",
584 | " 1687.0 | \n",
585 | "
\n",
586 | " \n",
587 | " | 1626691 | \n",
588 | " 117 | \n",
589 | " 168000691 | \n",
590 | " 2807548 | \n",
591 | " 161000755 | \n",
592 | " 2807626 | \n",
593 | " 13 | \n",
594 | " 844.0 | \n",
595 | "
\n",
596 | " \n",
597 | " | 1626692 | \n",
598 | " 117 | \n",
599 | " 161000461 | \n",
600 | " 2805703 | \n",
601 | " 161000584 | \n",
602 | " 2806807 | \n",
603 | " 14 | \n",
604 | " 50.0 | \n",
605 | "
\n",
606 | " \n",
607 | " | 1626693 | \n",
608 | " 117 | \n",
609 | " 161000584 | \n",
610 | " 2806807 | \n",
611 | " 161000650 | \n",
612 | " 2807439 | \n",
613 | " 15 | \n",
614 | " 13.0 | \n",
615 | "
\n",
616 | " \n",
617 | " | 1626694 | \n",
618 | " 117 | \n",
619 | " 161000650 | \n",
620 | " 2807439 | \n",
621 | " 161000460 | \n",
622 | " 2805702 | \n",
623 | " 16 | \n",
624 | " 17.0 | \n",
625 | "
\n",
626 | " \n",
627 | "
\n",
628 | "
"
629 | ],
630 | "text/plain": [
631 | " ROUTE_NAME F_STTN_ID F_STTN_ISC_ID T_STTN_ID T_STTN_ISC_ID STOP_SEQ \\\n",
632 | "1626690 117 168000690 2807549 168000691 2807548 11 \n",
633 | "1626691 117 168000691 2807548 161000755 2807626 13 \n",
634 | "1626692 117 161000461 2805703 161000584 2806807 14 \n",
635 | "1626693 117 161000584 2806807 161000650 2807439 15 \n",
636 | "1626694 117 161000650 2807439 161000460 2805702 16 \n",
637 | "\n",
638 | " TRANSIT_TIME \n",
639 | "1626690 1687.0 \n",
640 | "1626691 844.0 \n",
641 | "1626692 50.0 \n",
642 | "1626693 13.0 \n",
643 | "1626694 17.0 "
644 | ]
645 | },
646 | "execution_count": 9,
647 | "metadata": {},
648 | "output_type": "execute_result"
649 | }
650 | ],
651 | "source": [
652 | "\"\"\" bms_data에서 117노선의 정보만 추출 \"\"\"\n",
653 | "\"\"\" ----------------------------------- \"\"\"\n",
654 | "bms_data_df_117 = bms_data[bms_data['ROUTE_NAME']=='117']\n",
655 | "bms_data_df_117.head()"
656 | ]
657 | },
658 | {
659 | "cell_type": "code",
660 | "execution_count": 10,
661 | "metadata": {},
662 | "outputs": [
663 | {
664 | "data": {
665 | "text/plain": [
666 | "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]"
667 | ]
668 | },
669 | "execution_count": 10,
670 | "metadata": {},
671 | "output_type": "execute_result"
672 | }
673 | ],
674 | "source": [
675 | "\"\"\" 추출된 df에서 unique_stop_seq 추출 \"\"\"\n",
676 | "\"\"\" ----------------------------------- \"\"\"\n",
677 | "unique_stop_seq = sorted([int(i) for i in bms_data_df_117['STOP_SEQ'].unique()])\n",
678 | "unique_stop_seq"
679 | ]
680 | },
681 | {
682 | "cell_type": "code",
683 | "execution_count": 11,
684 | "metadata": {},
685 | "outputs": [],
686 | "source": [
687 | "\"\"\" issue2 해결을 위한 방법 \"\"\"\n",
688 | "\"\"\" 직전 i-1 row의 to stn을 기억한 후, \"\"\"\n",
689 | "\"\"\" 직전 i row의 from stn과 다를 경우, \"\"\"\n",
690 | "\"\"\" 직전 i-1 to stn, i from stn을 seq에 삽입 \"\"\"\n",
691 | "\"\"\" ---------------------------------------- \"\"\"\n",
692 | "i_1_value = bms_data_df_117[bms_data_df_117['STOP_SEQ']==str(unique_stop_seq[0])].values[0,1:5]\n",
693 | "i_1_from_stn, i_1_to_stn = i_1_value[0], i_1_value[2]\n",
694 | "seq_117 = [i_1_from_stn]\n",
695 | "\n",
696 | "for i in unique_stop_seq[1:]:\n",
697 | " value = bms_data_df_117[bms_data_df_117['STOP_SEQ']==str(i)].values[0,1:5]\n",
698 | " i_from_stn, i_to_stn = value[0],value[2]\n",
699 | " if i_1_to_stn == i_from_stn:\n",
700 | " seq_117.append(i_from_stn)\n",
701 | " i_1_from_stn, i_1_to_stn = i_from_stn, i_to_stn\n",
702 | " else:\n",
703 | " seq_117+=[i_1_to_stn,i_from_stn]\n",
704 | " i_1_from_stn, i_1_to_stn = i_from_stn, i_to_stn\n",
705 | " \n",
706 | "\"\"\"\n",
707 | "아래 시간맵 산출의 세부 issue 2에 의해 추가\n",
708 | "(중복되는 노선이 존재하여 제거)\n",
709 | "\"\"\"\n",
710 | "temp_copy = seq_117.copy()\n",
711 | "for i,stn1 in enumerate(temp_copy):\n",
712 | " for stn2 in temp_copy[i+1:]:\n",
713 | " if stn1==stn2:\n",
714 | " seq_117.remove(stn2)\n",
715 | " "
716 | ]
717 | },
718 | {
719 | "cell_type": "code",
720 | "execution_count": 12,
721 | "metadata": {
722 | "scrolled": false
723 | },
724 | "outputs": [
725 | {
726 | "data": {
727 | "text/plain": [
728 | "['161000452',\n",
729 | " '161000660',\n",
730 | " '161000510',\n",
731 | " '161000513',\n",
732 | " '161000455',\n",
733 | " '161000488',\n",
734 | " '161000457',\n",
735 | " '161000459',\n",
736 | " '161000651',\n",
737 | " '161000583',\n",
738 | " '161000462',\n",
739 | " '161000756',\n",
740 | " '168000690',\n",
741 | " '115000182',\n",
742 | " '168000691',\n",
743 | " '161000755',\n",
744 | " '161000461',\n",
745 | " '161000584',\n",
746 | " '161000650',\n",
747 | " '161000460',\n",
748 | " '161000458',\n",
749 | " '161000489',\n",
750 | " '161000456',\n",
751 | " '161000512',\n",
752 | " '161000537']"
753 | ]
754 | },
755 | "execution_count": 12,
756 | "metadata": {},
757 | "output_type": "execute_result"
758 | }
759 | ],
760 | "source": [
761 | "\"\"\"BMS DATA에 의해 복원된 117번 노선\"\"\"\n",
762 | "seq_117"
763 | ]
764 | },
765 | {
766 | "cell_type": "markdown",
767 | "metadata": {},
768 | "source": [
769 | "# 존치노선(598-1 제외)들의 노선도 산출"
770 | ]
771 | },
772 | {
773 | "cell_type": "code",
774 | "execution_count": 13,
775 | "metadata": {},
776 | "outputs": [
777 | {
778 | "name": "stderr",
779 | "output_type": "stream",
780 | "text": [
781 | "100%|██████████████████████████████████████████████████████████████████████████████████| 82/82 [00:43<00:00, 1.87it/s]\n"
782 | ]
783 | }
784 | ],
785 | "source": [
786 | "existed_routes_name = existed_routes_df['노선번호'].tolist()\n",
787 | "existed_routes_seq = {}\n",
788 | "for route_name in tqdm(existed_routes_name):\n",
789 | " if route_name == '598-1':continue\n",
790 | " \n",
791 | " bms_data_temp_df = bms_data[bms_data['ROUTE_NAME']==route_name]\n",
792 | " unique_stop_seq = sorted([int(i) for i in bms_data_temp_df['STOP_SEQ'].unique()])\n",
793 | " \n",
794 | " i_1_value = bms_data_temp_df[bms_data_temp_df['STOP_SEQ']==str(unique_stop_seq[0])].values[0,1:5]\n",
795 | " i_1_from_stn, i_1_to_stn = i_1_value[0], i_1_value[2]\n",
796 | " seq = [i_1_from_stn]\n",
797 | "\n",
798 | " for i in unique_stop_seq[1:]:\n",
799 | " value = bms_data_temp_df[bms_data_temp_df['STOP_SEQ']==str(i)].values[0,1:5]\n",
800 | " i_from_stn, i_to_stn = value[0],value[2]\n",
801 | " if i_1_to_stn == i_from_stn:\n",
802 | " seq.append(i_from_stn)\n",
803 | " i_1_from_stn, i_1_to_stn = i_from_stn, i_to_stn\n",
804 | " else:\n",
805 | " seq+=[i_1_to_stn,i_from_stn]\n",
806 | " i_1_from_stn, i_1_to_stn = i_from_stn, i_to_stn\n",
807 | " temp_copy = seq.copy()\n",
808 | " for i,stn1 in enumerate(temp_copy):\n",
809 | " for stn2 in temp_copy[i+1:]:\n",
810 | " if stn1==stn2:\n",
811 | " seq.remove(stn2)\n",
812 | " existed_routes_seq[route_name] = seq"
813 | ]
814 | },
815 | {
816 | "cell_type": "markdown",
817 | "metadata": {},
818 | "source": [
819 | "# 117번노선을 예시로 노선시간 산정\n",
820 | "\n",
821 | "```\n",
822 | "\n",
823 | "issue 1) 117번의 노선도는 아래와 같은데, *** stn을 i라 할때, (i,i+1) 운행기록이 없음\n",
824 | " \n",
825 | "['161000452', LH7단지\n",
826 | " '161000660', *** 센트럴푸르지오자이\n",
827 | " '161000510', 한양수자인(옆문)\n",
828 | " '161000513',\n",
829 | " '161000455',\n",
830 | " '161000488',\n",
831 | " '161000457',\n",
832 | " '161000459',\n",
833 | " '161000651',\n",
834 | " '161000583',\n",
835 | " '161000462', 우미린1단지후문\n",
836 | " '161000756', *** 영종KCC스위첸옆문\n",
837 | " '168000690', 인천공항TG(미정차)\n",
838 | " '168000691', *** 인천공항TG(미정차) <- 얘가 이상함(정류장이 중복되며, TG를 두번지나는게..)\n",
839 | " '115000182', 개화역(회차)\n",
840 | " '168000691', 인천공항TG(미정차)\n",
841 | " '161000755', *** 영종KCC스위첸옆문\n",
842 | " '161000461', 우미린1단지후문\n",
843 | " '161000584',\n",
844 | " '161000650',\n",
845 | " '161000460',\n",
846 | " '161000458',\n",
847 | " '161000489',\n",
848 | " '161000456',\n",
849 | " '161000512',\n",
850 | " '161000537']\n",
851 | " \n",
852 | " 세부 issue 1) LH7단지에서 센트럴푸르지오자이로 갔던 운행기록은 존재하나, 센트럴푸르지오자이에서 한양수자인(옆문)으로 갔던 운행기록이 존재하지 않음 \n",
853 | " 세부 issue 2) 위 리스트 중 '<-' 표시된 정류소로 인해 노선도가 기형적으로 변하며, 시간맵을 산정할 시, 문제가 됨\n",
854 | " \n",
855 | " sol 1) 운행기록이 없는것은 어쩔수없다고 판단, 시간맵 산정시 pass\n",
856 | " sol 2) 해당 경우는 회차지 근방(개화역)에서 승하차기록이 없는경우로 사료되며, 톨게이트에서 바로 다시 톨게이트로 오는 경우임. 따라서, 첫번째 168000691은 노선도에서 삭제를 해야함. <- how?) iteration을 i stn이 i+n stn과 중복된다면, i를 제거\n",
857 | " \n",
858 | " 바뀐 정류장 시퀀스\n",
859 | " \n",
860 | " ['161000452', LH7단지\n",
861 | " '161000660', *** 센트럴푸르지오자이\n",
862 | " '161000510', 한양수자인(옆문)\n",
863 | " ...\n",
864 | " '161000462', 우미린1단지후문\n",
865 | " '161000756', *** 영종KCC스위첸옆문\n",
866 | " '168000690', 인천공항TG(미정차)\n",
867 | " '115000182', 개화역(회차)\n",
868 | " '168000691', 인천공항TG(미정차)\n",
869 | " '161000755', *** 영종KCC스위첸옆문\n",
870 | " '161000461', 우미린1단지후문\n",
871 | " ...\n",
872 | " '161000537']\n",
873 | " \n",
874 | " ==================================================================\n",
875 | " ==================================================================\n",
876 | "\n",
877 | " issue 2) TG를 전후로하여 운행기록이 존재하지않음. 실제 정류소로보면 영종KCC스위첸옆문-개화역-영종KCC스위첸옆문이 오고가는 정류소임. TG를 지나는 비슷한 노선 308의 노선을 볼때는 다음과같으며, 117번과 달리 예쁘게 \\\\잘들어있음//\n",
878 | " \n",
879 | " ['232000080', 북변환승센터.구터미널(기점)\n",
880 | " ...\n",
881 | " '168000299', 서부공단입구\n",
882 | " '168001287', 북인천하부TG(미정차)\n",
883 | " '161000634', 금산IC(미정차)\n",
884 | " '161000203', 인천공항T1(3층7번)\n",
885 | " '161000556',\n",
886 | " '161000615', 인천공항T2(8)번출입구(3층) 회차\n",
887 | " ...\n",
888 | " '161000026', 국제업무단지(공항청사)\n",
889 | " '161000635', 금산IC(미정차)\n",
890 | " '168000901', 북인천하부TG(미정차)\n",
891 | " '168001034', 청라국제도시역\n",
892 | " ...\n",
893 | " '232000064'] 풍년마을.김포고(걸포사거리방면)\n",
894 | " \n",
895 | " sol) 기존노선의 시간맵 산정시, 문제 되지않을것으로 보이기 때문에 pass\n",
896 | " (실제로 117노선의 운행기록중 TG에서 개화역 운행기록의 약 20분은 영종하늘도시KCC스위첸에서 개화역과 동일)\n",
897 | "```"
898 | ]
899 | },
900 | {
901 | "cell_type": "code",
902 | "execution_count": 14,
903 | "metadata": {},
904 | "outputs": [
905 | {
906 | "data": {
907 | "text/plain": [
908 | "array([['12', '168000066', '2800760', ..., '2800741', '34', '32.0'],\n",
909 | " ['12', '168000085', '2800741', ..., '2800725', '35', '40.0'],\n",
910 | " ['12', '168000101', '2800725', ..., '2800691', '36', '186.0'],\n",
911 | " ...,\n",
912 | " ['540', '165000462', '2801941', ..., '2801944', '2', '53.0'],\n",
913 | " ['538', '165000443', '2801958', ..., '2801947', '5', '29.0'],\n",
914 | " ['538', '165000455', '2801947', ..., '2801939', '6', '30.0']],\n",
915 | " dtype=object)"
916 | ]
917 | },
918 | "execution_count": 14,
919 | "metadata": {},
920 | "output_type": "execute_result"
921 | }
922 | ],
923 | "source": [
924 | "\"\"\" 빠른 속도를 위해 dataframe이 아닌 array형식으로 time값 검색\"\"\"\n",
925 | "\"\"\" ------------------------------------------------------ \"\"\"\n",
926 | "bms_data_array = bms_data.values\n",
927 | "bms_data_array"
928 | ]
929 | },
930 | {
931 | "cell_type": "code",
932 | "execution_count": 15,
933 | "metadata": {
934 | "scrolled": true
935 | },
936 | "outputs": [
937 | {
938 | "data": {
939 | "text/plain": [
940 | "65.28947368421052"
941 | ]
942 | },
943 | "execution_count": 15,
944 | "metadata": {},
945 | "output_type": "execute_result"
946 | }
947 | ],
948 | "source": [
949 | "\"\"\" 117노선이 161000452(LH7단지)와 \"\"\"\n",
950 | "\"\"\" 161000660(센트럴푸르지오자이)을 다닌 시간들을 산출 \"\"\"\n",
951 | "\"\"\" ----------------------------------------------\"\"\"\n",
952 | "_117_array = bms_data_array[bms_data_array[:,0]=='117']\n",
953 | "stn1_array = _117_array[_117_array[:,1]=='161000452']\n",
954 | "stn1stn2_array = stn1_array[stn1_array[:,3]=='161000660']\n",
955 | "\n",
956 | "time_array = stn1stn2_array[:,-1].astype(float)\n",
957 | "time_array.mean()"
958 | ]
959 | },
960 | {
961 | "cell_type": "code",
962 | "execution_count": 16,
963 | "metadata": {},
964 | "outputs": [
965 | {
966 | "data": {
967 | "text/plain": [
968 | "65.64936897971688"
969 | ]
970 | },
971 | "execution_count": 16,
972 | "metadata": {},
973 | "output_type": "execute_result"
974 | }
975 | ],
976 | "source": [
977 | "\"\"\" 117노선의 노선도를 통해 산출 \"\"\"\n",
978 | "\"\"\" ---------------------------- \"\"\"\n",
979 | "t_117 = 0\n",
980 | "_117_array = bms_data_array[bms_data_array[:,0]=='117']\n",
981 | "for stn1,stn2 in zip(existed_routes_seq['117'][:-1],existed_routes_seq['117'][1:]):\n",
982 | " stn1_array = _117_array[_117_array[:,1]==stn1]\n",
983 | " stn1stn2_array = stn1_array[stn1_array[:,3]==stn2]\n",
984 | " \n",
985 | " time_array = stn1stn2_array[:,-1].astype(float)\n",
986 | " if len(time_array)==0:continue\n",
987 | " time_avg = time_array.mean()\n",
988 | " t_117+=time_avg/60\n",
989 | "t_117 ## 위의 65.289는 초이고, 아래 65.649는 분입니다"
990 | ]
991 | },
992 | {
993 | "cell_type": "markdown",
994 | "metadata": {},
995 | "source": [
996 | "# 존치노선 운행시간 산정\n",
997 | "\n",
998 | "```\n",
999 | "issue 1) 특정 노선의 타임이 너무큼\n",
1000 | "ex)\n",
1001 | "12번 산출값 = 737.88, 인가시간 = 294\n",
1002 | " 2번 산출값 = 713.17, 인가시간 = 237\n",
1003 | " \n",
1004 | "sol) \n",
1005 | "구간 평균 운행시간이 10분이상이며, 해당 구간의 직선거리를 통한 평균속도가 5km/h 미만인 구간은 제외\n",
1006 | "평균속도가 5km/h 미만인 구간은 휴식을 취한 구간이라고 판단\n",
1007 | "```"
1008 | ]
1009 | },
1010 | {
1011 | "cell_type": "code",
1012 | "execution_count": 17,
1013 | "metadata": {
1014 | "scrolled": true
1015 | },
1016 | "outputs": [],
1017 | "source": [
1018 | "quantile_values = [0, 0.1, 0.2, 0.3, 0.4, 0.5]\n",
1019 | "\n",
1020 | "result = pd.DataFrame(index = existed_routes_name, columns=quantile_values)\n",
1021 | "for quantile_value in quantile_values: \n",
1022 | " existed_routes_time = {}\n",
1023 | " bms_data_array = bms_data.values\n",
1024 | " for route_name in existed_routes_name:\n",
1025 | " if route_name=='598-1':continue\n",
1026 | " t = 0\n",
1027 | " _array = bms_data_array[bms_data_array[:,0]==route_name] ## route_name에 해당된 모든 기록 array\n",
1028 | " for stn1,stn2 in zip(existed_routes_seq[route_name][:-1],existed_routes_seq[route_name][1:]):\n",
1029 | " stn1_array = _array[_array[:,1]==stn1]\n",
1030 | " stn1stn2_array = stn1_array[stn1_array[:,3]==stn2]\n",
1031 | " time_array = stn1stn2_array[:,-1].astype(float) ## route_name 이 stn1과 stn2를 운행한 기록 array\n",
1032 | " if len(time_array)==0:continue\n",
1033 | " ## 117번과 같은 경우, time_array가 빈 리스트일수 있으나, 무시하면됨\n",
1034 | "\n",
1035 | " #######################################\n",
1036 | " ############ ##########\n",
1037 | " ############ 상위 하위 조절 ##########\n",
1038 | " ############ ##########\n",
1039 | " #######################################\n",
1040 | "\n",
1041 | " quantile = np.quantile(time_array, quantile_value, interpolation='nearest')\n",
1042 | " time_array = time_array[time_array>=quantile]\n",
1043 | "\n",
1044 | " time_avg = time_array.mean()/60\n",
1045 | "\n",
1046 | " #######################################\n",
1047 | " ############ ##########\n",
1048 | " ############ issue 1 ##########\n",
1049 | " ############ ##########\n",
1050 | " #######################################\n",
1051 | " if time_avg>10:\n",
1052 | " stn1_name,stn1_lat,stn1_lon = find_stn_status(stn1)\n",
1053 | " stn2_name,stn2_lat,stn2_lon = find_stn_status(stn2)\n",
1054 | " dist = haversine(float(stn1_lat),float(stn1_lon),float(stn2_lat),float(stn2_lon))\n",
1055 | " if dist/(time_avg/60) < 5:\n",
1056 | " ## 버스 뒤에서 밀어서 운행하는 속도수준은 제외(maybe 휴식시간)\n",
1057 | " continue\n",
1058 | " t+=time_avg\n",
1059 | " existed_routes_time[route_name] = t\n",
1060 | " for route_name in existed_routes_time:\n",
1061 | " result.loc[route_name,quantile_value] = existed_routes_time[route_name]"
1062 | ]
1063 | },
1064 | {
1065 | "cell_type": "code",
1066 | "execution_count": 18,
1067 | "metadata": {},
1068 | "outputs": [
1069 | {
1070 | "data": {
1071 | "text/html": [
1072 | "\n",
1073 | "\n",
1086 | "
\n",
1087 | " \n",
1088 | " \n",
1089 | " | \n",
1090 | " 0.0 | \n",
1091 | " 0.1 | \n",
1092 | " 0.2 | \n",
1093 | " 0.3 | \n",
1094 | " 0.4 | \n",
1095 | " 0.5 | \n",
1096 | "
\n",
1097 | " \n",
1098 | " \n",
1099 | " \n",
1100 | " | 117 | \n",
1101 | " 65.6494 | \n",
1102 | " 67.6872 | \n",
1103 | " 69.9731 | \n",
1104 | " 72.1295 | \n",
1105 | " 74.5348 | \n",
1106 | " 76.4947 | \n",
1107 | "
\n",
1108 | " \n",
1109 | " | 10 | \n",
1110 | " 161.236 | \n",
1111 | " 169.59 | \n",
1112 | " 177.871 | \n",
1113 | " 186.654 | \n",
1114 | " 196.401 | \n",
1115 | " 206.485 | \n",
1116 | "
\n",
1117 | " \n",
1118 | " | 103 | \n",
1119 | " 232.082 | \n",
1120 | " 245.299 | \n",
1121 | " 259.217 | \n",
1122 | " 274.525 | \n",
1123 | " 291.239 | \n",
1124 | " 309.556 | \n",
1125 | "
\n",
1126 | " \n",
1127 | " | 111 | \n",
1128 | " 169.188 | \n",
1129 | " 176.763 | \n",
1130 | " 184.917 | \n",
1131 | " 193.347 | \n",
1132 | " 202.167 | \n",
1133 | " 212.395 | \n",
1134 | "
\n",
1135 | " \n",
1136 | " | 112 | \n",
1137 | " 225.325 | \n",
1138 | " 237.544 | \n",
1139 | " 250.2 | \n",
1140 | " 263.527 | \n",
1141 | " 277.078 | \n",
1142 | " 292.237 | \n",
1143 | "
\n",
1144 | " \n",
1145 | " | ... | \n",
1146 | " ... | \n",
1147 | " ... | \n",
1148 | " ... | \n",
1149 | " ... | \n",
1150 | " ... | \n",
1151 | " ... | \n",
1152 | "
\n",
1153 | " \n",
1154 | " | 800 | \n",
1155 | " 257.149 | \n",
1156 | " 267.727 | \n",
1157 | " 277.767 | \n",
1158 | " 288.172 | \n",
1159 | " 299.18 | \n",
1160 | " 311.898 | \n",
1161 | "
\n",
1162 | " \n",
1163 | " | 905 | \n",
1164 | " 194.403 | \n",
1165 | " 204.943 | \n",
1166 | " 205.255 | \n",
1167 | " 215.554 | \n",
1168 | " 226.788 | \n",
1169 | " 239.01 | \n",
1170 | "
\n",
1171 | " \n",
1172 | " | 908 | \n",
1173 | " 119.565 | \n",
1174 | " 125.196 | \n",
1175 | " 130.486 | \n",
1176 | " 136.13 | \n",
1177 | " 142.126 | \n",
1178 | " 148.697 | \n",
1179 | "
\n",
1180 | " \n",
1181 | " | 909 | \n",
1182 | " 146.361 | \n",
1183 | " 153.588 | \n",
1184 | " 160.701 | \n",
1185 | " 168.072 | \n",
1186 | " 175.739 | \n",
1187 | " 183.908 | \n",
1188 | "
\n",
1189 | " \n",
1190 | " | 순환31 | \n",
1191 | " 23.8378 | \n",
1192 | " 25.0048 | \n",
1193 | " 26.2389 | \n",
1194 | " 27.5931 | \n",
1195 | " 29.0595 | \n",
1196 | " 30.5708 | \n",
1197 | "
\n",
1198 | " \n",
1199 | "
\n",
1200 | "
82 rows × 6 columns
\n",
1201 | "
"
1202 | ],
1203 | "text/plain": [
1204 | " 0.0 0.1 0.2 0.3 0.4 0.5\n",
1205 | "117 65.6494 67.6872 69.9731 72.1295 74.5348 76.4947\n",
1206 | "10 161.236 169.59 177.871 186.654 196.401 206.485\n",
1207 | "103 232.082 245.299 259.217 274.525 291.239 309.556\n",
1208 | "111 169.188 176.763 184.917 193.347 202.167 212.395\n",
1209 | "112 225.325 237.544 250.2 263.527 277.078 292.237\n",
1210 | "... ... ... ... ... ... ...\n",
1211 | "800 257.149 267.727 277.767 288.172 299.18 311.898\n",
1212 | "905 194.403 204.943 205.255 215.554 226.788 239.01\n",
1213 | "908 119.565 125.196 130.486 136.13 142.126 148.697\n",
1214 | "909 146.361 153.588 160.701 168.072 175.739 183.908\n",
1215 | "순환31 23.8378 25.0048 26.2389 27.5931 29.0595 30.5708\n",
1216 | "\n",
1217 | "[82 rows x 6 columns]"
1218 | ]
1219 | },
1220 | "execution_count": 18,
1221 | "metadata": {},
1222 | "output_type": "execute_result"
1223 | }
1224 | ],
1225 | "source": [
1226 | "result"
1227 | ]
1228 | },
1229 | {
1230 | "cell_type": "code",
1231 | "execution_count": 19,
1232 | "metadata": {
1233 | "scrolled": true
1234 | },
1235 | "outputs": [],
1236 | "source": [
1237 | "# result.to_csv('존치노선_전수검사0814.csv',encoding='utf8')"
1238 | ]
1239 | },
1240 | {
1241 | "cell_type": "markdown",
1242 | "metadata": {},
1243 | "source": [
1244 | "# 변경,신설 노선을 위한 시간맵 작성\n",
1245 | "# 511번노선을 예시로 노선시간 산정\n",
1246 | "```\n",
1247 | "기존노선의 운행시간 산출에 사용된 방식을 적용하며, 적절한 정류장간 이격거리를 위해 정류장간 운행시간이 1분 미만인 운행기록은 삭제\n",
1248 | "\n",
1249 | "511의 경로에 다닥다닥붙은게 존재하기에 선정\n",
1250 | "\n",
1251 | "issue 1) 링크에 정류장을 할당하다보니 정류장이 다닥다닥 붙어있을 수있음\n",
1252 | "\n",
1253 | "sol) 기존노선의 운행시간 산출에 사용된 방식을 적용하였기에, 정확하진않으나 근사값을 산출할수있음\n",
1254 | "how) route_seq = [1,2,3,4,5]라 가정할때, i번째 정류장과 연결된 가장 가까운 i+n의 seq의 time을 할당한 후, i+n 정류장 부터 반복\n",
1255 | "```"
1256 | ]
1257 | },
1258 | {
1259 | "cell_type": "code",
1260 | "execution_count": 20,
1261 | "metadata": {},
1262 | "outputs": [
1263 | {
1264 | "name": "stderr",
1265 | "output_type": "stream",
1266 | "text": [
1267 | "100%|█████████████████████████████████████████████████████████████████████| 6680193/6680193 [2:54:58<00:00, 636.29it/s]\n"
1268 | ]
1269 | }
1270 | ],
1271 | "source": [
1272 | "\"\"\" time_array를 할당한 후, 위와같이, 거리 및 속도 조건을 걸경우, \"\"\"\n",
1273 | "\"\"\" 정상적인 데이터가 날아갈 위험이 있음 \"\"\"\n",
1274 | "\"\"\" 따라서 각 row마다 해당 조건을 걸어줌 \"\"\"\n",
1275 | "\"\"\" time_map = {(stn1,stn2):[time_list],(stn1,stn2):[time_list]}\"\"\"\n",
1276 | "\"\"\" ---------------------------------------------------------- \"\"\"\n",
1277 | "## 시간 오래걸리니 조심\n",
1278 | "time_map = {}\n",
1279 | "bms_data_array = bms_data.values\n",
1280 | "for row in tqdm(bms_data_array):\n",
1281 | " route_name, stn1_id, stn1_isc_id, stn2_id, stn2_isc_id, stop_seq, time = row\n",
1282 | " time = float(time)/60\n",
1283 | " \n",
1284 | " if stn1_id==stn2_id:continue\n",
1285 | " if time<1:continue\n",
1286 | " \n",
1287 | " stn1_name,stn1_lat,stn1_lon = find_stn_status(stn1_id)\n",
1288 | " stn2_name,stn2_lat,stn2_lon = find_stn_status(stn2_id)\n",
1289 | " \n",
1290 | " dist = haversine(float(stn1_lat),float(stn1_lon),float(stn2_lat),float(stn2_lon))\n",
1291 | " \n",
1292 | " if dist/(float(time)/60) < 3:\n",
1293 | " ## 버스 뒤에서 밀어서 운행하는 속도수준은 제외(maybe 휴식시간)\n",
1294 | " continue\n",
1295 | " try:\n",
1296 | " time_map[(stn1_isc_id,stn2_isc_id)].append(float(time))\n",
1297 | " except KeyError:\n",
1298 | " time_map[(stn1_isc_id,stn2_isc_id)] = [float(time)] \n"
1299 | ]
1300 | },
1301 | {
1302 | "cell_type": "code",
1303 | "execution_count": 21,
1304 | "metadata": {},
1305 | "outputs": [
1306 | {
1307 | "data": {
1308 | "text/plain": [
1309 | "'165000464'"
1310 | ]
1311 | },
1312 | "execution_count": 21,
1313 | "metadata": {},
1314 | "output_type": "execute_result"
1315 | }
1316 | ],
1317 | "source": [
1318 | "stn2_id"
1319 | ]
1320 | },
1321 | {
1322 | "cell_type": "code",
1323 | "execution_count": 22,
1324 | "metadata": {},
1325 | "outputs": [
1326 | {
1327 | "data": {
1328 | "text/html": [
1329 | "\n",
1330 | "\n",
1343 | "
\n",
1344 | " \n",
1345 | " \n",
1346 | " | \n",
1347 | " 노선 id | \n",
1348 | " 노선명 | \n",
1349 | " 정류장명 | \n",
1350 | " 정류장 ID | \n",
1351 | " 노선명 텍스트 | \n",
1352 | "
\n",
1353 | " \n",
1354 | " \n",
1355 | " \n",
1356 | " | 0 | \n",
1357 | " 28001001 | \n",
1358 | " 9100 | \n",
1359 | " 숭의역(1번출구) | \n",
1360 | " 2802621 | \n",
1361 | " 9100 | \n",
1362 | "
\n",
1363 | " \n",
1364 | " | 1 | \n",
1365 | " 28001001 | \n",
1366 | " 9100 | \n",
1367 | " 숭의로터리 | \n",
1368 | " 2802809 | \n",
1369 | " 9100 | \n",
1370 | "
\n",
1371 | " \n",
1372 | " | 2 | \n",
1373 | " 28001001 | \n",
1374 | " 9100 | \n",
1375 | " 제물포역 | \n",
1376 | " 2802635 | \n",
1377 | " 9100 | \n",
1378 | "
\n",
1379 | " \n",
1380 | " | 3 | \n",
1381 | " 28001001 | \n",
1382 | " 9100 | \n",
1383 | " 주안사거리 | \n",
1384 | " 2802617 | \n",
1385 | " 9100 | \n",
1386 | "
\n",
1387 | " \n",
1388 | " | 4 | \n",
1389 | " 28001001 | \n",
1390 | " 9100 | \n",
1391 | " 석바위 | \n",
1392 | " 2802728 | \n",
1393 | " 9100 | \n",
1394 | "
\n",
1395 | " \n",
1396 | "
\n",
1397 | "
"
1398 | ],
1399 | "text/plain": [
1400 | " 노선 id 노선명 정류장명 정류장 ID 노선명 텍스트\n",
1401 | "0 28001001 9100 숭의역(1번출구) 2802621 9100\n",
1402 | "1 28001001 9100 숭의로터리 2802809 9100\n",
1403 | "2 28001001 9100 제물포역 2802635 9100\n",
1404 | "3 28001001 9100 주안사거리 2802617 9100\n",
1405 | "4 28001001 9100 석바위 2802728 9100"
1406 | ]
1407 | },
1408 | "execution_count": 22,
1409 | "metadata": {},
1410 | "output_type": "execute_result"
1411 | }
1412 | ],
1413 | "source": [
1414 | "kisti_routes_seq = pd.read_excel('20200806_V12_경유정류장순서_서민호(200810.v1.김민기).xlsx',\n",
1415 | " sheet_name='노선, 정류장 정보',dtype=str)\n",
1416 | "kisti_routes_seq.head()"
1417 | ]
1418 | },
1419 | {
1420 | "cell_type": "code",
1421 | "execution_count": 23,
1422 | "metadata": {
1423 | "scrolled": true
1424 | },
1425 | "outputs": [
1426 | {
1427 | "data": {
1428 | "text/plain": [
1429 | "['2807441',\n",
1430 | " '2806808',\n",
1431 | " '2806914',\n",
1432 | " '2802920',\n",
1433 | " '2807167',\n",
1434 | " '2802898',\n",
1435 | " '2802895',\n",
1436 | " '2802894',\n",
1437 | " '2802887',\n",
1438 | " '2802862',\n",
1439 | " '2802803',\n",
1440 | " '2802774',\n",
1441 | " '2802760',\n",
1442 | " '2802617',\n",
1443 | " '2802733',\n",
1444 | " '2807110',\n",
1445 | " '2802710',\n",
1446 | " '2802734',\n",
1447 | " '2802756',\n",
1448 | " '2805155',\n",
1449 | " '2802794',\n",
1450 | " '2802852',\n",
1451 | " '2802880',\n",
1452 | " '2802890',\n",
1453 | " '2802893',\n",
1454 | " '2802896',\n",
1455 | " '2805500',\n",
1456 | " '2802934',\n",
1457 | " '2806811',\n",
1458 | " '2806809']"
1459 | ]
1460 | },
1461 | "execution_count": 23,
1462 | "metadata": {},
1463 | "output_type": "execute_result"
1464 | }
1465 | ],
1466 | "source": [
1467 | "seq_511 = kisti_routes_seq[kisti_routes_seq['노선명 텍스트']=='511']['정류장 ID'].tolist()\n",
1468 | "seq_511"
1469 | ]
1470 | },
1471 | {
1472 | "cell_type": "code",
1473 | "execution_count": 24,
1474 | "metadata": {
1475 | "scrolled": true
1476 | },
1477 | "outputs": [
1478 | {
1479 | "data": {
1480 | "text/plain": [
1481 | "59.456317999136175"
1482 | ]
1483 | },
1484 | "execution_count": 24,
1485 | "metadata": {},
1486 | "output_type": "execute_result"
1487 | }
1488 | ],
1489 | "source": [
1490 | "\"\"\"511노선 산정 시간\"\"\"\n",
1491 | "stn1 = seq_511[0]\n",
1492 | "t_511 = 0\n",
1493 | "while True:\n",
1494 | " for stn2 in seq_511[seq_511.index(stn1)+1:]:\n",
1495 | " try:\n",
1496 | " time_array = np.array(time_map[(stn1,stn2)])\n",
1497 | " quantile = np.quantile(time_array, 0.3, interpolation='nearest')\n",
1498 | " time_array = time_array[time_array>=quantile]\n",
1499 | " \n",
1500 | " t_511+=time_array.mean()\n",
1501 | " stn1 = stn2\n",
1502 | " break\n",
1503 | " except KeyError:\n",
1504 | " continue\n",
1505 | " if stn2==seq_511[-1]:break\n",
1506 | "t_511"
1507 | ]
1508 | },
1509 | {
1510 | "attachments": {
1511 | "image.png": {
1512 | "image/png": "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"
1513 | }
1514 | },
1515 | "cell_type": "markdown",
1516 | "metadata": {},
1517 | "source": [
1518 | "# 전체노선 적용\n",
1519 | "\n",
1520 | "```\n",
1521 | "issue 1) kisti노선에서 상행에서 이미한번 들린 정류소를 하행에서 들리는 경우가 있음\n",
1522 | "\n",
1523 | "sol) 117번노선을 예시로 노선시간 산정의 세부 issue 2 와 같다고 판단하여 하행시 방문하는 중복된 정류소는 제거\n",
1524 | "\n",
1525 | "issue 2) 모든 경로가 time_map에서 검색이 안되는경우가 있을수있음\n",
1526 | "\n",
1527 | "sol) i번째 정류소에서부터 i+n 정류소 간의 time_map 기록이 없을 경우, (i,i+1)의 평균속력인 거리/15로 time을 계산한후, i+1정류소부터 다시 탐색\n",
1528 | "\n",
1529 | "issue 3) 204_변경에서 정류장 sequence에 nan값이 들어있음\n",
1530 | "ex)\n",
1531 | "[nan,\n",
1532 | " '2806541',\n",
1533 | " '2806543',\n",
1534 | " '2805676',\n",
1535 | " '2805630',\n",
1536 | " '2807038'...]\n",
1537 | " \n",
1538 | " sol) nan값이 들어있는지 체크하고 사전제거\n",
1539 | " \n",
1540 | " issue 4) 위도경도값이 0인 정류소들이 존재\n",
1541 | " ex)무의지소\n",
1542 | "```\n",
1543 | "\n",
1544 | "\n",
1545 | "```\n",
1546 | "sol) time_map값 및 위경도 값도 없으니 pass\n",
1547 | "\n",
1548 | "issue 5) 정류소현황목록에서 검색이 되지않는 정류소가 있음(also kisti data)\n",
1549 | "\n",
1550 | "sol) pass\n",
1551 | "```"
1552 | ]
1553 | },
1554 | {
1555 | "cell_type": "code",
1556 | "execution_count": 25,
1557 | "metadata": {
1558 | "scrolled": false
1559 | },
1560 | "outputs": [],
1561 | "source": [
1562 | "quantile_values = [0,0.1,0.2,0.3,0.4,0.5]\n",
1563 | "\n",
1564 | "result = pd.DataFrame(index = kisti_routes_seq['노선명 텍스트'].unique(),columns=quantile_values)\n",
1565 | "for quantile_value in quantile_values:\n",
1566 | " routes_time = {}\n",
1567 | " for route_name in kisti_routes_seq['노선명 텍스트'].unique():\n",
1568 | " seq = kisti_routes_seq[kisti_routes_seq['노선명 텍스트']==route_name]['정류장 ID'].tolist()\n",
1569 | " \n",
1570 | " \"\"\"issue 3\"\"\"\n",
1571 | " seq = [stn for stn in seq if type(stn)==str]\n",
1572 | " ###################################################\n",
1573 | " \"\"\"issue 1\"\"\"\n",
1574 | " temp_copy = seq.copy()\n",
1575 | " for i,stn1 in enumerate(temp_copy):\n",
1576 | " for stn2 in temp_copy[i+1:]:\n",
1577 | " if stn1==stn2:\n",
1578 | " seq.remove(stn2)\n",
1579 | " ####################################################\n",
1580 | " \n",
1581 | " stn1 = seq[0]\n",
1582 | " t = 0\n",
1583 | " while True:\n",
1584 | " for stn2 in seq[seq.index(stn1)+1:seq.index(stn1)+4]:\n",
1585 | " ## 뒤 몇개의 정류소까지 확인해볼꺼냐. 만약 길게한다면 점프뛰어버릴수도있음\n",
1586 | " ## 링크당 최대 정류장갯수를 산정하여 넣는것도 방법일듯\n",
1587 | " stack=0\n",
1588 | " try:\n",
1589 | " time_array = np.array(time_map[(stn1,stn2)])\n",
1590 | " quantile = np.quantile(time_array, quantile_value, interpolation='nearest')\n",
1591 | " time_array = time_array[time_array>=quantile]\n",
1592 | " t+=time_array.mean()\n",
1593 | " stn1 = stn2\n",
1594 | " stack+=1\n",
1595 | " break\n",
1596 | " except KeyError:\n",
1597 | " continue\n",
1598 | " if stn1 == seq[-1]:break\n",
1599 | " if stack==1:continue\n",
1600 | " \n",
1601 | " ##################################################################\n",
1602 | " \"\"\"issue 2\"\"\"\n",
1603 | " stn2 = seq[seq.index(stn1)+1]\n",
1604 | " ##################################\n",
1605 | " \"\"\"issue 4 및 5\"\"\"\n",
1606 | " try:\n",
1607 | " stn1_name,stn1_lat,stn1_lon = find_stn_status(stn1)\n",
1608 | " stn2_name,stn2_lat,stn2_lon = find_stn_status(stn2)\n",
1609 | " except IndexError:\n",
1610 | " stn1=stn2\n",
1611 | " continue\n",
1612 | " if stn1_lat==0:## 무의지소 case\n",
1613 | " stn1=stn2\n",
1614 | " continue\n",
1615 | " ###################################\n",
1616 | " dist = haversine(float(stn1_lat),float(stn1_lon),float(stn2_lat),float(stn2_lon))\n",
1617 | " t += ((dist*60*(1+quantile_value))/15)\n",
1618 | " stn1=stn2\n",
1619 | " if stn1 == seq[-1]:break\n",
1620 | " ####################################################################\n",
1621 | " routes_time[route_name] = t\n",
1622 | " for route_name in routes_time:\n",
1623 | " result.loc[route_name,quantile_value] = routes_time[route_name]"
1624 | ]
1625 | },
1626 | {
1627 | "cell_type": "code",
1628 | "execution_count": 26,
1629 | "metadata": {},
1630 | "outputs": [
1631 | {
1632 | "data": {
1633 | "text/html": [
1634 | "\n",
1635 | "\n",
1648 | "
\n",
1649 | " \n",
1650 | " \n",
1651 | " | \n",
1652 | " 0.0 | \n",
1653 | " 0.1 | \n",
1654 | " 0.2 | \n",
1655 | " 0.3 | \n",
1656 | " 0.4 | \n",
1657 | " 0.5 | \n",
1658 | "
\n",
1659 | " \n",
1660 | " \n",
1661 | " \n",
1662 | " | 9100 | \n",
1663 | " 189.303 | \n",
1664 | " 196.316 | \n",
1665 | " 203.065 | \n",
1666 | " 210.236 | \n",
1667 | " 218.177 | \n",
1668 | " 227.403 | \n",
1669 | "
\n",
1670 | " \n",
1671 | " | 9200 | \n",
1672 | " 184.905 | \n",
1673 | " 191.955 | \n",
1674 | " 199.013 | \n",
1675 | " 206.448 | \n",
1676 | " 214.696 | \n",
1677 | " 224.306 | \n",
1678 | "
\n",
1679 | " \n",
1680 | " | 9300 | \n",
1681 | " 247.226 | \n",
1682 | " 258.465 | \n",
1683 | " 269.585 | \n",
1684 | " 281.143 | \n",
1685 | " 294.022 | \n",
1686 | " 308.618 | \n",
1687 | "
\n",
1688 | " \n",
1689 | " | 9201 | \n",
1690 | " 165.65 | \n",
1691 | " 171.34 | \n",
1692 | " 176.928 | \n",
1693 | " 182.826 | \n",
1694 | " 189.229 | \n",
1695 | " 196.677 | \n",
1696 | "
\n",
1697 | " \n",
1698 | " | 14-1_변경 | \n",
1699 | " 203.367 | \n",
1700 | " 209.701 | \n",
1701 | " 216.878 | \n",
1702 | " 224.197 | \n",
1703 | " 232.323 | \n",
1704 | " 240.803 | \n",
1705 | "
\n",
1706 | " \n",
1707 | " | ... | \n",
1708 | " ... | \n",
1709 | " ... | \n",
1710 | " ... | \n",
1711 | " ... | \n",
1712 | " ... | \n",
1713 | " ... | \n",
1714 | "
\n",
1715 | " \n",
1716 | " | 781 | \n",
1717 | " 146.752 | \n",
1718 | " 152.19 | \n",
1719 | " 157.685 | \n",
1720 | " 163.296 | \n",
1721 | " 169.069 | \n",
1722 | " 175.078 | \n",
1723 | "
\n",
1724 | " \n",
1725 | " | 99 | \n",
1726 | " 155.87 | \n",
1727 | " 163.389 | \n",
1728 | " 170.843 | \n",
1729 | " 178.711 | \n",
1730 | " 186.991 | \n",
1731 | " 195.954 | \n",
1732 | "
\n",
1733 | " \n",
1734 | " | 98 | \n",
1735 | " 102.569 | \n",
1736 | " 106.963 | \n",
1737 | " 111.68 | \n",
1738 | " 116.468 | \n",
1739 | " 121.888 | \n",
1740 | " 127.196 | \n",
1741 | "
\n",
1742 | " \n",
1743 | " | 95 | \n",
1744 | " 235.841 | \n",
1745 | " 245.094 | \n",
1746 | " 255.13 | \n",
1747 | " 265.338 | \n",
1748 | " 276.176 | \n",
1749 | " 287.936 | \n",
1750 | "
\n",
1751 | " \n",
1752 | " | 592-1_신설 | \n",
1753 | " 60.4944 | \n",
1754 | " 63.8002 | \n",
1755 | " 67.2816 | \n",
1756 | " 70.8802 | \n",
1757 | " 74.4528 | \n",
1758 | " 78.2289 | \n",
1759 | "
\n",
1760 | " \n",
1761 | "
\n",
1762 | "
264 rows × 6 columns
\n",
1763 | "
"
1764 | ],
1765 | "text/plain": [
1766 | " 0.0 0.1 0.2 0.3 0.4 0.5\n",
1767 | "9100 189.303 196.316 203.065 210.236 218.177 227.403\n",
1768 | "9200 184.905 191.955 199.013 206.448 214.696 224.306\n",
1769 | "9300 247.226 258.465 269.585 281.143 294.022 308.618\n",
1770 | "9201 165.65 171.34 176.928 182.826 189.229 196.677\n",
1771 | "14-1_변경 203.367 209.701 216.878 224.197 232.323 240.803\n",
1772 | "... ... ... ... ... ... ...\n",
1773 | "781 146.752 152.19 157.685 163.296 169.069 175.078\n",
1774 | "99 155.87 163.389 170.843 178.711 186.991 195.954\n",
1775 | "98 102.569 106.963 111.68 116.468 121.888 127.196\n",
1776 | "95 235.841 245.094 255.13 265.338 276.176 287.936\n",
1777 | "592-1_신설 60.4944 63.8002 67.2816 70.8802 74.4528 78.2289\n",
1778 | "\n",
1779 | "[264 rows x 6 columns]"
1780 | ]
1781 | },
1782 | "execution_count": 26,
1783 | "metadata": {},
1784 | "output_type": "execute_result"
1785 | }
1786 | ],
1787 | "source": [
1788 | "result"
1789 | ]
1790 | },
1791 | {
1792 | "cell_type": "code",
1793 | "execution_count": 106,
1794 | "metadata": {},
1795 | "outputs": [],
1796 | "source": [
1797 | "# result.to_csv('kisti노선_전수검사0814_ver2.csv',encoding='utf-8-sig')"
1798 | ]
1799 | },
1800 | {
1801 | "cell_type": "markdown",
1802 | "metadata": {},
1803 | "source": [
1804 | "# "
1805 | ]
1806 | },
1807 | {
1808 | "cell_type": "code",
1809 | "execution_count": 70,
1810 | "metadata": {},
1811 | "outputs": [],
1812 | "source": [
1813 | "quantile_values = [(0.,0.8),(0.2,0.8),(0.2,1.)]\n",
1814 | "\n",
1815 | "result = pd.DataFrame(columns=['노선번호','정류장 id']+quantile_values)\n",
1816 | "for route_name in kisti_routes_seq['노선명 텍스트'].unique():\n",
1817 | " seq = kisti_routes_seq[kisti_routes_seq['노선명 텍스트']==route_name]['정류장 ID'].tolist()\n",
1818 | "\n",
1819 | " \"\"\"issue 3\"\"\"\n",
1820 | " seq = [stn for stn in seq if type(stn)==str]\n",
1821 | " ###################################################\n",
1822 | " \"\"\"issue 1\"\"\"\n",
1823 | " temp_copy = seq.copy()\n",
1824 | " for i,stn1 in enumerate(temp_copy):\n",
1825 | " for stn2 in temp_copy[i+1:]:\n",
1826 | " if stn1==stn2:\n",
1827 | " seq.remove(stn2)\n",
1828 | " ####################################################\n",
1829 | "\n",
1830 | " stn1 = seq[0]\n",
1831 | " t_2000 = 0\n",
1832 | " t_2080 = 0\n",
1833 | " t_0080 = 0\n",
1834 | " result.loc[len(result)] = [route_name,stn1,0,0,0]\n",
1835 | " while True:\n",
1836 | " for stn2 in seq[seq.index(stn1)+1:seq.index(stn1)+4]:\n",
1837 | " ## 뒤 몇개의 정류소까지 확인해볼꺼냐. 만약 길게한다면 점프뛰어버릴수도있음\n",
1838 | " ## 링크당 최대 정류장갯수를 산정하여 넣는것도 방법일듯\n",
1839 | " stack=0\n",
1840 | " try:\n",
1841 | " time_array = np.array(time_map[(stn1,stn2)])\n",
1842 | " quantile_20 = np.quantile(time_array, 0.2, interpolation='nearest')\n",
1843 | " quantile_80 = np.quantile(time_array, 0.8, interpolation='nearest')\n",
1844 | "\n",
1845 | " time_array_2000 = time_array[time_array>=quantile_20]\n",
1846 | " time_array_2080 = time_array_2000[time_array_2000<=quantile_80]\n",
1847 | " time_array_0080 = time_array[time_array<=quantile_80]\n",
1848 | " \n",
1849 | " t_2000 += time_array_2000.mean()\n",
1850 | " t_2080 += time_array_2080.mean()\n",
1851 | " t_0080 += time_array_0080.mean()\n",
1852 | " \n",
1853 | " result.loc[len(result)] = [route_name,stn2,\n",
1854 | " time.strftime('%H:%M:%S', time.gmtime(timedelta(minutes=t_2000).total_seconds())),\n",
1855 | " time.strftime('%H:%M:%S', time.gmtime(timedelta(minutes=t_2080).total_seconds())),\n",
1856 | " time.strftime('%H:%M:%S', time.gmtime(timedelta(minutes=t_0080).total_seconds())),]\n",
1857 | " \n",
1858 | " stn1 = stn2\n",
1859 | " stack+=1\n",
1860 | " break\n",
1861 | " except KeyError:\n",
1862 | " continue\n",
1863 | " if stn1 == seq[-1]:break\n",
1864 | " if stack==1:continue\n",
1865 | "\n",
1866 | " ##################################################################\n",
1867 | " \"\"\"issue 2\"\"\"\n",
1868 | " stn2 = seq[seq.index(stn1)+1]\n",
1869 | " ##################################\n",
1870 | " \"\"\"issue 4 및 5\"\"\"\n",
1871 | " try:\n",
1872 | " stn1_name,stn1_lat,stn1_lon = find_stn_status(stn1)\n",
1873 | " stn2_name,stn2_lat,stn2_lon = find_stn_status(stn2)\n",
1874 | " except IndexError:\n",
1875 | " stn1=stn2\n",
1876 | " continue\n",
1877 | " if stn1_lat==0:## 무의지소 case\n",
1878 | " stn1=stn2\n",
1879 | " continue\n",
1880 | " ###################################\n",
1881 | " dist = haversine(float(stn1_lat),float(stn1_lon),float(stn2_lat),float(stn2_lon))\n",
1882 | " t_2000 += ((dist*60*(1+0.2))/15)\n",
1883 | " t_2080 += (dist*60/15)\n",
1884 | " t_0080 += ((dist*60*(1-0.2))/15)\n",
1885 | " result.loc[len(result)] = [route_name,stn2,\n",
1886 | " time.strftime('%H:%M:%S', time.gmtime(timedelta(minutes=t_2000).total_seconds())),\n",
1887 | " time.strftime('%H:%M:%S', time.gmtime(timedelta(minutes=t_2080).total_seconds())),\n",
1888 | " time.strftime('%H:%M:%S', time.gmtime(timedelta(minutes=t_0080).total_seconds())),]\n",
1889 | " \n",
1890 | " stn1=stn2\n",
1891 | " if stn1 == seq[-1]:break\n",
1892 | " ####################################################################"
1893 | ]
1894 | },
1895 | {
1896 | "cell_type": "code",
1897 | "execution_count": 71,
1898 | "metadata": {},
1899 | "outputs": [
1900 | {
1901 | "data": {
1902 | "text/html": [
1903 | "\n",
1904 | "\n",
1917 | "
\n",
1918 | " \n",
1919 | " \n",
1920 | " | \n",
1921 | " 노선번호 | \n",
1922 | " 정류장 id | \n",
1923 | " (0.0, 0.8) | \n",
1924 | " (0.2, 0.8) | \n",
1925 | " (0.2, 1.0) | \n",
1926 | "
\n",
1927 | " \n",
1928 | " \n",
1929 | " \n",
1930 | " | 0 | \n",
1931 | " 9100 | \n",
1932 | " 2802621 | \n",
1933 | " 0 | \n",
1934 | " 0 | \n",
1935 | " 0 | \n",
1936 | "
\n",
1937 | " \n",
1938 | " | 1 | \n",
1939 | " 9100 | \n",
1940 | " 2802809 | \n",
1941 | " 00:03:08 | \n",
1942 | " 00:02:36 | \n",
1943 | " 00:02:23 | \n",
1944 | "
\n",
1945 | " \n",
1946 | " | 2 | \n",
1947 | " 9100 | \n",
1948 | " 2802635 | \n",
1949 | " 00:07:50 | \n",
1950 | " 00:06:51 | \n",
1951 | " 00:06:21 | \n",
1952 | "
\n",
1953 | " \n",
1954 | " | 3 | \n",
1955 | " 9100 | \n",
1956 | " 2802617 | \n",
1957 | " 00:13:24 | \n",
1958 | " 00:11:53 | \n",
1959 | " 00:11:01 | \n",
1960 | "
\n",
1961 | " \n",
1962 | " | 4 | \n",
1963 | " 9100 | \n",
1964 | " 2802728 | \n",
1965 | " 00:16:50 | \n",
1966 | " 00:14:52 | \n",
1967 | " 00:13:39 | \n",
1968 | "
\n",
1969 | " \n",
1970 | " | ... | \n",
1971 | " ... | \n",
1972 | " ... | \n",
1973 | " ... | \n",
1974 | " ... | \n",
1975 | " ... | \n",
1976 | "
\n",
1977 | " \n",
1978 | " | 20543 | \n",
1979 | " 592-1_신설 | \n",
1980 | " 2801324 | \n",
1981 | " 01:02:36 | \n",
1982 | " 00:54:37 | \n",
1983 | " 00:48:24 | \n",
1984 | "
\n",
1985 | " \n",
1986 | " | 20544 | \n",
1987 | " 592-1_신설 | \n",
1988 | " 2801331 | \n",
1989 | " 01:02:58 | \n",
1990 | " 00:54:55 | \n",
1991 | " 00:48:39 | \n",
1992 | "
\n",
1993 | " \n",
1994 | " | 20545 | \n",
1995 | " 592-1_신설 | \n",
1996 | " 2801344 | \n",
1997 | " 01:04:31 | \n",
1998 | " 00:56:21 | \n",
1999 | " 00:49:59 | \n",
2000 | "
\n",
2001 | " \n",
2002 | " | 20546 | \n",
2003 | " 592-1_신설 | \n",
2004 | " 2801357 | \n",
2005 | " 01:05:56 | \n",
2006 | " 00:57:36 | \n",
2007 | " 00:51:12 | \n",
2008 | "
\n",
2009 | " \n",
2010 | " | 20547 | \n",
2011 | " 592-1_신설 | \n",
2012 | " 2801360 | \n",
2013 | " 01:07:16 | \n",
2014 | " 00:58:52 | \n",
2015 | " 00:52:25 | \n",
2016 | "
\n",
2017 | " \n",
2018 | "
\n",
2019 | "
20548 rows × 5 columns
\n",
2020 | "
"
2021 | ],
2022 | "text/plain": [
2023 | " 노선번호 정류장 id (0.0, 0.8) (0.2, 0.8) (0.2, 1.0)\n",
2024 | "0 9100 2802621 0 0 0\n",
2025 | "1 9100 2802809 00:03:08 00:02:36 00:02:23\n",
2026 | "2 9100 2802635 00:07:50 00:06:51 00:06:21\n",
2027 | "3 9100 2802617 00:13:24 00:11:53 00:11:01\n",
2028 | "4 9100 2802728 00:16:50 00:14:52 00:13:39\n",
2029 | "... ... ... ... ... ...\n",
2030 | "20543 592-1_신설 2801324 01:02:36 00:54:37 00:48:24\n",
2031 | "20544 592-1_신설 2801331 01:02:58 00:54:55 00:48:39\n",
2032 | "20545 592-1_신설 2801344 01:04:31 00:56:21 00:49:59\n",
2033 | "20546 592-1_신설 2801357 01:05:56 00:57:36 00:51:12\n",
2034 | "20547 592-1_신설 2801360 01:07:16 00:58:52 00:52:25\n",
2035 | "\n",
2036 | "[20548 rows x 5 columns]"
2037 | ]
2038 | },
2039 | "execution_count": 71,
2040 | "metadata": {},
2041 | "output_type": "execute_result"
2042 | }
2043 | ],
2044 | "source": [
2045 | "result"
2046 | ]
2047 | },
2048 | {
2049 | "cell_type": "code",
2050 | "execution_count": 67,
2051 | "metadata": {},
2052 | "outputs": [
2053 | {
2054 | "name": "stdout",
2055 | "output_type": "stream",
2056 | "text": [
2057 | "The duration was 00:57:06\n"
2058 | ]
2059 | }
2060 | ],
2061 | "source": [
2062 | "import time\n",
2063 | "from datetime import datetime, timedelta\n",
2064 | "\n",
2065 | "td = timedelta(minutes=57.116)\n",
2066 | "print('The duration was {0}'.format(time.strftime('%H:%M:%S', time.gmtime(td.total_seconds()))))"
2067 | ]
2068 | },
2069 | {
2070 | "cell_type": "code",
2071 | "execution_count": 69,
2072 | "metadata": {},
2073 | "outputs": [
2074 | {
2075 | "data": {
2076 | "text/plain": [
2077 | "'00:57:06'"
2078 | ]
2079 | },
2080 | "execution_count": 69,
2081 | "metadata": {},
2082 | "output_type": "execute_result"
2083 | }
2084 | ],
2085 | "source": [
2086 | "time.strftime('%H:%M:%S', time.gmtime(td.total_seconds()))"
2087 | ]
2088 | }
2089 | ],
2090 | "metadata": {
2091 | "kernelspec": {
2092 | "display_name": "Python 3",
2093 | "language": "python",
2094 | "name": "python3"
2095 | },
2096 | "language_info": {
2097 | "codemirror_mode": {
2098 | "name": "ipython",
2099 | "version": 3
2100 | },
2101 | "file_extension": ".py",
2102 | "mimetype": "text/x-python",
2103 | "name": "python",
2104 | "nbconvert_exporter": "python",
2105 | "pygments_lexer": "ipython3",
2106 | "version": "3.7.4"
2107 | }
2108 | },
2109 | "nbformat": 4,
2110 | "nbformat_minor": 2
2111 | }
2112 |
--------------------------------------------------------------------------------