├── 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 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | " \n", 222 | " \n", 223 | " \n", 224 | "
정류소 번호정류소 IDISC 정류소 ID위도경도
0373191630003192802757126.6801883043328637.457360395358165
1373261630003262802755126.6799270381157837.45776642315442
2422281680002282800619126.6733945296890537.52184277702059
3401581660001582801688126.7112675172972437.490948333960574
4891461680011462806735126.6169775917577937.559185515339
\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 | " \n", 331 | " \n", 332 | " \n", 333 | " \n", 334 | " \n", 335 | " \n", 336 | " \n", 337 | " \n", 338 | " \n", 339 | " \n", 340 | " \n", 341 | " \n", 342 | " \n", 343 | " \n", 344 | " \n", 345 | " \n", 346 | " \n", 347 | " \n", 348 | " \n", 349 | " \n", 350 | " \n", 351 | " \n", 352 | " \n", 353 | " \n", 354 | " \n", 355 | " \n", 356 | " \n", 357 | " \n", 358 | " \n", 359 | " \n", 360 | " \n", 361 | " \n", 362 | " \n", 363 | " \n", 364 | " \n", 365 | " \n", 366 | " \n", 367 | " \n", 368 | " \n", 369 | " \n", 370 | " \n", 371 | " \n", 372 | " \n", 373 | " \n", 374 | " \n", 375 | " \n", 376 | " \n", 377 | " \n", 378 | " \n", 379 | " \n", 380 | " \n", 381 | " \n", 382 | " \n", 383 | " \n", 384 | " \n", 385 | " \n", 386 | " \n", 387 | " \n", 388 | " \n", 389 | " \n", 390 | " \n", 391 | " \n", 392 | " \n", 393 | " \n", 394 | " \n", 395 | " \n", 396 | " \n", 397 | " \n", 398 | " \n", 399 | " \n", 400 | " \n", 401 | " \n", 402 | " \n", 403 | " \n", 404 | " \n", 405 | " \n", 406 | " \n", 407 | " \n", 408 | " \n", 409 | " \n", 410 | " \n", 411 | " \n", 412 | " \n", 413 | " \n", 414 | " \n", 415 | " \n", 416 | " \n", 417 | " \n", 418 | " \n", 419 | " \n", 420 | " \n", 421 | " \n", 422 | " \n", 423 | " \n", 424 | " \n", 425 | " \n", 426 | " \n", 427 | " \n", 428 | " \n", 429 | " \n", 430 | " \n", 431 | " \n", 432 | " \n", 433 | " \n", 434 | " \n", 435 | " \n", 436 | " \n", 437 | " \n", 438 | " \n", 439 | " \n", 440 | " \n", 441 | " \n", 442 | " \n", 443 | " \n", 444 | " \n", 445 | " \n", 446 | " \n", 447 | " \n", 448 | " \n", 449 | " \n", 450 | " \n", 451 | " \n", 452 | " \n", 453 | " \n", 454 | " \n", 455 | " \n", 456 | " \n", 457 | " \n", 458 | " \n", 459 | " \n", 460 | " \n", 461 | " \n", 462 | " \n", 463 | " \n", 464 | " \n", 465 | " \n", 466 | " \n", 467 | " \n", 468 | " \n", 469 | " \n", 470 | " \n", 471 | " \n", 472 | " \n", 473 | " \n", 474 | " \n", 475 | " \n", 476 | " \n", 477 | " \n", 478 | " \n", 479 | " \n", 480 | " \n", 481 | " \n", 482 | " \n", 483 | " \n", 484 | " \n", 485 | " \n", 486 | " \n", 487 | " \n", 488 | " \n", 489 | " \n", 490 | " \n", 491 | " \n", 492 | " \n", 493 | " \n", 494 | " \n", 495 | " \n", 496 | " \n", 497 | " \n", 498 | " \n", 499 | " \n", 500 | " \n", 501 | " \n", 502 | " \n", 503 | " \n", 504 | " \n", 505 | " \n", 506 | " \n", 507 | " \n", 508 | " \n", 509 | " \n", 510 | " \n", 511 | " \n", 512 | " \n", 513 | " \n", 514 | " \n", 515 | " \n", 516 | " \n", 517 | " \n", 518 | " \n", 519 | " \n", 520 | " \n", 521 | " \n", 522 | " \n", 523 | " \n", 524 | " \n", 525 | " \n", 526 | " \n", 527 | " \n", 528 | " \n", 529 | " \n", 530 | " \n", 531 | " \n", 532 | " \n", 533 | " \n", 534 | " \n", 535 | " \n", 536 | " \n", 537 | " \n", 538 | " \n", 539 | " \n", 540 | " \n", 541 | " \n", 542 | " \n", 543 | " \n", 544 | " \n", 545 | " \n", 546 | " \n", 547 | " \n", 548 | " \n", 549 | " \n", 550 | " \n", 551 | " \n", 552 | " \n", 553 | " \n", 554 | " \n", 555 | " \n", 556 | " \n", 557 | " \n", 558 | " \n", 559 | " \n", 560 | " \n", 561 | " \n", 562 | " \n", 563 | " \n", 564 | " \n", 565 | " \n", 566 | " \n", 567 | " \n", 568 | " \n", 569 | " \n", 570 | " \n", 571 | " \n", 572 | " \n", 573 | " \n", 574 | " \n", 575 | " \n", 576 | " \n", 577 | " \n", 578 | " \n", 579 | " \n", 580 | " \n", 581 | " \n", 582 | " \n", 583 | " \n", 584 | " \n", 585 | " \n", 586 | " \n", 587 | " \n", 588 | " \n", 589 | " \n", 590 | " \n", 591 | " \n", 592 | " \n", 593 | " \n", 594 | " \n", 595 | " \n", 596 | " \n", 597 | " \n", 598 | " \n", 599 | " \n", 600 | " \n", 601 | " \n", 602 | " \n", 603 | " \n", 604 | " \n", 605 | " \n", 606 | " \n", 607 | " \n", 608 | " \n", 609 | " \n", 610 | " \n", 611 | " \n", 612 | " \n", 613 | " \n", 614 | " \n", 615 | " \n", 616 | " \n", 617 | " \n", 618 | " \n", 619 | " \n", 620 | " \n", 621 | " \n", 622 | " \n", 623 | " \n", 624 | " \n", 625 | " \n", 626 | " \n", 627 | " \n", 628 | " \n", 629 | " \n", 630 | " \n", 631 | " \n", 632 | " \n", 633 | " \n", 634 | " \n", 635 | " \n", 636 | " \n", 637 | " \n", 638 | " \n", 639 | " \n", 640 | "
정류소명정류소표준ID정류소단축ID노선ID노선번호정류소순번버스유형
17224독배로317번길(삼거리)163000634376341650000735111지선
17225SK스카이뷰104동163000587375871650000735112지선
17226SK스카이뷰109동163000607376071650000735113지선
17227굴다리163000142371421650000735114지선
17228용현고가교163000611376111650000735115지선
17229인하대후문163000165371651650000735116지선
17230정석항공과학고163000168371681650000735117지선
17231학산소극장163000169371691650000735118지선
17232용남파출소163000177371771650000735119지선
17233용일사거리1630002083720816500007351110지선
17234인천기계공고1630002723727216500007351111지선
17235주안2동치안센터1630003023730216500007351112지선
17236제일시장1630003163731616500007351113지선
17237주안사거리1630005143751416500007351114지선
17238교보생명1630003573735716500007351115지선
17239주안역환승정류장1630006173761716500007351116지선
17240주안1동행정복지센터1630003853738516500007351117지선
17241도화IC1630003563735616500007351118지선
17242롯데월드타워1630003253732516500007351119지선
17243인천기계공고1630005373753716500007351120지선
17244인천기계공고1630002813728116500007351121지선
17245용일사거리1630002183721816500007351122지선
17246용남파출소1630001843718416500007351123지선
17247학산소극장1630001733717316500007351124지선
17248정석항공과학고1630001703717016500007351125지선
17249인하대후문1630001673716716500007351126지선
17250용현고가교1630005503755016500007351127지선
17251인하대역3번출구1630001273712716500007351128지선
17252인하대역1630005963759616500007351129지선
17253SK스카이뷰1630006013760116500007351130지선
\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 | " \n", 74 | " \n", 75 | " \n", 76 | " \n", 77 | " \n", 78 | " \n", 79 | " \n", 80 | " \n", 81 | " \n", 82 | " \n", 83 | " \n", 84 | " \n", 85 | " \n", 86 | " \n", 87 | " \n", 88 | " \n", 89 | " \n", 90 | " \n", 91 | " \n", 92 | " \n", 93 | " \n", 94 | " \n", 95 | " \n", 96 | " \n", 97 | " \n", 98 | " \n", 99 | " \n", 100 | " \n", 101 | " \n", 102 | " \n", 103 | " \n", 104 | " \n", 105 | " \n", 106 | " \n", 107 | " \n", 108 | " \n", 109 | " \n", 110 | " \n", 111 | " \n", 112 | " \n", 113 | " \n", 114 | " \n", 115 | " \n", 116 | " \n", 117 | " \n", 118 | " \n", 119 | " \n", 120 | " \n", 121 | " \n", 122 | "
Sttn IdSttn Isc IdSttn NameSttn LatSttn Lon
02320000772800001양도마을.대림아파트37.604731898126.722346797
12320000762800002양도마을.대림아파트37.604322917126.722033457
22320000752800003수행마을37.607893558126.723575258
32320000742800004수행마을37.607893308126.723216093
42320000732800005유현마을.신동아아파트37.59642183126.721286176
\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 | " \n", 174 | " \n", 175 | " \n", 176 | " \n", 177 | " \n", 178 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 183 | " \n", 184 | " \n", 185 | " \n", 186 | " \n", 187 | " \n", 188 | " \n", 189 | " \n", 190 | " \n", 191 | " \n", 192 | " \n", 193 | " \n", 194 | " \n", 195 | " \n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 204 | " \n", 205 | " \n", 206 | " \n", 207 | " \n", 208 | " \n", 209 | " \n", 210 | " \n", 211 | " \n", 212 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 217 | " \n", 218 | " \n", 219 | " \n", 220 | " \n", 221 | "
정류소 명정류소 IDISC 정류소 ID위도경도
0(구)시민회관사거리1630003192802757126.6801883043328637.457360395358165
1(구)시민회관사거리1630003262802755126.6799270381157837.45776642315442
2(구)신현주공1680002282800619126.6733945296890537.52184277702059
3(구)현대백화점1660001582801688126.7112675172972437.490948333960574
4(주)경동세라믹스1680011462806735126.6169775917577937.559185515339
\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 | " \n", 292 | " \n", 293 | " \n", 294 | " \n", 295 | " \n", 296 | " \n", 297 | " \n", 298 | " \n", 299 | " \n", 300 | " \n", 301 | " \n", 302 | " \n", 303 | " \n", 304 | " \n", 305 | " \n", 306 | " \n", 307 | " \n", 308 | " \n", 309 | " \n", 310 | " \n", 311 | " \n", 312 | " \n", 313 | " \n", 314 | " \n", 315 | " \n", 316 | " \n", 317 | " \n", 318 | " \n", 319 | " \n", 320 | " \n", 321 | " \n", 322 | " \n", 323 | " \n", 324 | " \n", 325 | " \n", 326 | " \n", 327 | " \n", 328 | " \n", 329 | " \n", 330 | " \n", 331 | " \n", 332 | " \n", 333 | " \n", 334 | " \n", 335 | " \n", 336 | " \n", 337 | " \n", 338 | " \n", 339 | " \n", 340 | " \n", 341 | " \n", 342 | " \n", 343 | " \n", 344 | " \n", 345 | " \n", 346 | " \n", 347 | " \n", 348 | " \n", 349 | " \n", 350 | " \n", 351 | " \n", 352 | "
ROUTE_NAMEF_STTN_IDF_STTN_ISC_IDT_STTN_IDT_STTN_ISC_IDSTOP_SEQTRANSIT_TIME
012168000066280076016800008528007413432.0
112168000085280074116800010128007253540.0
2121680001012800725168000136280069136186.0
312168000136280069116800014328006843748.0
4121680001432800684168000151280067638119.0
\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 | " \n", 417 | " \n", 418 | " \n", 419 | " \n", 420 | " \n", 421 | " \n", 422 | " \n", 423 | " \n", 424 | " \n", 425 | " \n", 426 | " \n", 427 | " \n", 428 | " \n", 429 | " \n", 430 | " \n", 431 | " \n", 432 | " \n", 433 | " \n", 434 | " \n", 435 | " \n", 436 | " \n", 437 | " \n", 438 | " \n", 439 | " \n", 440 | " \n", 441 | "
노선번호운행시간
0117105
110216
2103276
3111275
4112265
\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 | " \n", 567 | " \n", 568 | " \n", 569 | " \n", 570 | " \n", 571 | " \n", 572 | " \n", 573 | " \n", 574 | " \n", 575 | " \n", 576 | " \n", 577 | " \n", 578 | " \n", 579 | " \n", 580 | " \n", 581 | " \n", 582 | " \n", 583 | " \n", 584 | " \n", 585 | " \n", 586 | " \n", 587 | " \n", 588 | " \n", 589 | " \n", 590 | " \n", 591 | " \n", 592 | " \n", 593 | " \n", 594 | " \n", 595 | " \n", 596 | " \n", 597 | " \n", 598 | " \n", 599 | " \n", 600 | " \n", 601 | " \n", 602 | " \n", 603 | " \n", 604 | " \n", 605 | " \n", 606 | " \n", 607 | " \n", 608 | " \n", 609 | " \n", 610 | " \n", 611 | " \n", 612 | " \n", 613 | " \n", 614 | " \n", 615 | " \n", 616 | " \n", 617 | " \n", 618 | " \n", 619 | " \n", 620 | " \n", 621 | " \n", 622 | " \n", 623 | " \n", 624 | " \n", 625 | " \n", 626 | " \n", 627 | "
ROUTE_NAMEF_STTN_IDF_STTN_ISC_IDT_STTN_IDT_STTN_ISC_IDSTOP_SEQTRANSIT_TIME
162669011716800069028075491680006912807548111687.0
16266911171680006912807548161000755280762613844.0
1626692117161000461280570316100058428068071450.0
1626693117161000584280680716100065028074391513.0
1626694117161000650280743916100046028057021617.0
\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 | " \n", 1091 | " \n", 1092 | " \n", 1093 | " \n", 1094 | " \n", 1095 | " \n", 1096 | " \n", 1097 | " \n", 1098 | " \n", 1099 | " \n", 1100 | " \n", 1101 | " \n", 1102 | " \n", 1103 | " \n", 1104 | " \n", 1105 | " \n", 1106 | " \n", 1107 | " \n", 1108 | " \n", 1109 | " \n", 1110 | " \n", 1111 | " \n", 1112 | " \n", 1113 | " \n", 1114 | " \n", 1115 | " \n", 1116 | " \n", 1117 | " \n", 1118 | " \n", 1119 | " \n", 1120 | " \n", 1121 | " \n", 1122 | " \n", 1123 | " \n", 1124 | " \n", 1125 | " \n", 1126 | " \n", 1127 | " \n", 1128 | " \n", 1129 | " \n", 1130 | " \n", 1131 | " \n", 1132 | " \n", 1133 | " \n", 1134 | " \n", 1135 | " \n", 1136 | " \n", 1137 | " \n", 1138 | " \n", 1139 | " \n", 1140 | " \n", 1141 | " \n", 1142 | " \n", 1143 | " \n", 1144 | " \n", 1145 | " \n", 1146 | " \n", 1147 | " \n", 1148 | " \n", 1149 | " \n", 1150 | " \n", 1151 | " \n", 1152 | " \n", 1153 | " \n", 1154 | " \n", 1155 | " \n", 1156 | " \n", 1157 | " \n", 1158 | " \n", 1159 | " \n", 1160 | " \n", 1161 | " \n", 1162 | " \n", 1163 | " \n", 1164 | " \n", 1165 | " \n", 1166 | " \n", 1167 | " \n", 1168 | " \n", 1169 | " \n", 1170 | " \n", 1171 | " \n", 1172 | " \n", 1173 | " \n", 1174 | " \n", 1175 | " \n", 1176 | " \n", 1177 | " \n", 1178 | " \n", 1179 | " \n", 1180 | " \n", 1181 | " \n", 1182 | " \n", 1183 | " \n", 1184 | " \n", 1185 | " \n", 1186 | " \n", 1187 | " \n", 1188 | " \n", 1189 | " \n", 1190 | " \n", 1191 | " \n", 1192 | " \n", 1193 | " \n", 1194 | " \n", 1195 | " \n", 1196 | " \n", 1197 | " \n", 1198 | " \n", 1199 | "
0.00.10.20.30.40.5
11765.649467.687269.973172.129574.534876.4947
10161.236169.59177.871186.654196.401206.485
103232.082245.299259.217274.525291.239309.556
111169.188176.763184.917193.347202.167212.395
112225.325237.544250.2263.527277.078292.237
.....................
800257.149267.727277.767288.172299.18311.898
905194.403204.943205.255215.554226.788239.01
908119.565125.196130.486136.13142.126148.697
909146.361153.588160.701168.072175.739183.908
순환3123.837825.004826.238927.593129.059530.5708
\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 | " \n", 1348 | " \n", 1349 | " \n", 1350 | " \n", 1351 | " \n", 1352 | " \n", 1353 | " \n", 1354 | " \n", 1355 | " \n", 1356 | " \n", 1357 | " \n", 1358 | " \n", 1359 | " \n", 1360 | " \n", 1361 | " \n", 1362 | " \n", 1363 | " \n", 1364 | " \n", 1365 | " \n", 1366 | " \n", 1367 | " \n", 1368 | " \n", 1369 | " \n", 1370 | " \n", 1371 | " \n", 1372 | " \n", 1373 | " \n", 1374 | " \n", 1375 | " \n", 1376 | " \n", 1377 | " \n", 1378 | " \n", 1379 | " \n", 1380 | " \n", 1381 | " \n", 1382 | " \n", 1383 | " \n", 1384 | " \n", 1385 | " \n", 1386 | " \n", 1387 | " \n", 1388 | " \n", 1389 | " \n", 1390 | " \n", 1391 | " \n", 1392 | " \n", 1393 | " \n", 1394 | " \n", 1395 | " \n", 1396 | "
노선 id노선명정류장명정류장 ID노선명 텍스트
0280010019100숭의역(1번출구)28026219100
1280010019100숭의로터리28028099100
2280010019100제물포역28026359100
3280010019100주안사거리28026179100
4280010019100석바위28027289100
\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 | "![image.png](attachment:image.png)\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 | " \n", 1653 | " \n", 1654 | " \n", 1655 | " \n", 1656 | " \n", 1657 | " \n", 1658 | " \n", 1659 | " \n", 1660 | " \n", 1661 | " \n", 1662 | " \n", 1663 | " \n", 1664 | " \n", 1665 | " \n", 1666 | " \n", 1667 | " \n", 1668 | " \n", 1669 | " \n", 1670 | " \n", 1671 | " \n", 1672 | " \n", 1673 | " \n", 1674 | " \n", 1675 | " \n", 1676 | " \n", 1677 | " \n", 1678 | " \n", 1679 | " \n", 1680 | " \n", 1681 | " \n", 1682 | " \n", 1683 | " \n", 1684 | " \n", 1685 | " \n", 1686 | " \n", 1687 | " \n", 1688 | " \n", 1689 | " \n", 1690 | " \n", 1691 | " \n", 1692 | " \n", 1693 | " \n", 1694 | " \n", 1695 | " \n", 1696 | " \n", 1697 | " \n", 1698 | " \n", 1699 | " \n", 1700 | " \n", 1701 | " \n", 1702 | " \n", 1703 | " \n", 1704 | " \n", 1705 | " \n", 1706 | " \n", 1707 | " \n", 1708 | " \n", 1709 | " \n", 1710 | " \n", 1711 | " \n", 1712 | " \n", 1713 | " \n", 1714 | " \n", 1715 | " \n", 1716 | " \n", 1717 | " \n", 1718 | " \n", 1719 | " \n", 1720 | " \n", 1721 | " \n", 1722 | " \n", 1723 | " \n", 1724 | " \n", 1725 | " \n", 1726 | " \n", 1727 | " \n", 1728 | " \n", 1729 | " \n", 1730 | " \n", 1731 | " \n", 1732 | " \n", 1733 | " \n", 1734 | " \n", 1735 | " \n", 1736 | " \n", 1737 | " \n", 1738 | " \n", 1739 | " \n", 1740 | " \n", 1741 | " \n", 1742 | " \n", 1743 | " \n", 1744 | " \n", 1745 | " \n", 1746 | " \n", 1747 | " \n", 1748 | " \n", 1749 | " \n", 1750 | " \n", 1751 | " \n", 1752 | " \n", 1753 | " \n", 1754 | " \n", 1755 | " \n", 1756 | " \n", 1757 | " \n", 1758 | " \n", 1759 | " \n", 1760 | " \n", 1761 | "
0.00.10.20.30.40.5
9100189.303196.316203.065210.236218.177227.403
9200184.905191.955199.013206.448214.696224.306
9300247.226258.465269.585281.143294.022308.618
9201165.65171.34176.928182.826189.229196.677
14-1_변경203.367209.701216.878224.197232.323240.803
.....................
781146.752152.19157.685163.296169.069175.078
99155.87163.389170.843178.711186.991195.954
98102.569106.963111.68116.468121.888127.196
95235.841245.094255.13265.338276.176287.936
592-1_신설60.494463.800267.281670.880274.452878.2289
\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 | " \n", 1923 | " \n", 1924 | " \n", 1925 | " \n", 1926 | " \n", 1927 | " \n", 1928 | " \n", 1929 | " \n", 1930 | " \n", 1931 | " \n", 1932 | " \n", 1933 | " \n", 1934 | " \n", 1935 | " \n", 1936 | " \n", 1937 | " \n", 1938 | " \n", 1939 | " \n", 1940 | " \n", 1941 | " \n", 1942 | " \n", 1943 | " \n", 1944 | " \n", 1945 | " \n", 1946 | " \n", 1947 | " \n", 1948 | " \n", 1949 | " \n", 1950 | " \n", 1951 | " \n", 1952 | " \n", 1953 | " \n", 1954 | " \n", 1955 | " \n", 1956 | " \n", 1957 | " \n", 1958 | " \n", 1959 | " \n", 1960 | " \n", 1961 | " \n", 1962 | " \n", 1963 | " \n", 1964 | " \n", 1965 | " \n", 1966 | " \n", 1967 | " \n", 1968 | " \n", 1969 | " \n", 1970 | " \n", 1971 | " \n", 1972 | " \n", 1973 | " \n", 1974 | " \n", 1975 | " \n", 1976 | " \n", 1977 | " \n", 1978 | " \n", 1979 | " \n", 1980 | " \n", 1981 | " \n", 1982 | " \n", 1983 | " \n", 1984 | " \n", 1985 | " \n", 1986 | " \n", 1987 | " \n", 1988 | " \n", 1989 | " \n", 1990 | " \n", 1991 | " \n", 1992 | " \n", 1993 | " \n", 1994 | " \n", 1995 | " \n", 1996 | " \n", 1997 | " \n", 1998 | " \n", 1999 | " \n", 2000 | " \n", 2001 | " \n", 2002 | " \n", 2003 | " \n", 2004 | " \n", 2005 | " \n", 2006 | " \n", 2007 | " \n", 2008 | " \n", 2009 | " \n", 2010 | " \n", 2011 | " \n", 2012 | " \n", 2013 | " \n", 2014 | " \n", 2015 | " \n", 2016 | " \n", 2017 | " \n", 2018 | "
노선번호정류장 id(0.0, 0.8)(0.2, 0.8)(0.2, 1.0)
091002802621000
19100280280900:03:0800:02:3600:02:23
29100280263500:07:5000:06:5100:06:21
39100280261700:13:2400:11:5300:11:01
49100280272800:16:5000:14:5200:13:39
..................
20543592-1_신설280132401:02:3600:54:3700:48:24
20544592-1_신설280133101:02:5800:54:5500:48:39
20545592-1_신설280134401:04:3100:56:2100:49:59
20546592-1_신설280135701:05:5600:57:3600:51:12
20547592-1_신설280136001:07:1600:58:5200:52:25
\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 | --------------------------------------------------------------------------------