이번에는 공공데이터를 활용하여서 , 시각화 해 볼것이다.
사용할 사이트는 공공데이터 포털 https://www.data.go.kr/ 이다 .
버스노선정보를 가져와서 버스의 실시간 위치 정보를 google map api를 통해서 시각화 해 볼 것이다.
코드를 통해서 설명해 보겠다.
library(XML)
library(ggmap)
è 우선 사용할 패키지는 위와같다. 없다면 설치해 준다.
아참 , 들어가기 앞서서 , 공공데이터 포털에서 API 인증키를 받고 사용하는 법을 알아야한다.
회원가입은 되어있다는 가정하에 설명해 보겠다.
내가 사용할 API의 이름은 “노선정보조회 서비스” 이다 .
들어가서 다음과 같이 자신이 사용하는 목적을 클릭한다 .
나는 다음 기능 들을 다 사용할 것이다.
위 사진을 보면 일반 인증키라는 곳이 보이는데 , 데이터포털 사이트에서는 api를 제공하는 대신에 인증키를 받아서 사용하게 되어있다.
인증키를 받고 , 참고문서를 본다.
나는 주로 참고문서 or Document를 보는 편이다.
보면 정말 친절하게 설명이 나와있다.
참고문서를 확인해 보자 .
# 참고문서를 보면 strSrch는 검색할 노선번호를 의미한다는 것을 알 수 있다.
그리고 REST 형태로 URI 요청을 하는 예제를 보여주고 있다 .
이 형태로 주소창에 요청을 한다면 응답메시지가 이렇게 나온다는 것을 보여주고 있다.
이 내용을 토대로 어떻게 접근해야 할지 감이 잡히는 것이다.
url <- paste("http://ws.bus.go.kr/api/rest/busRouteInfo/getBusRouteList?serviceKey=gH19buRy%2BiHenMjC6JkiwE6VEG1Mq1WChoYviIkZ3J5KsdshhG4N5MddOCsefPhYDOrfHH5ani2qhOR%2FiQRtpg%3D%3D&strSrch=146")
è url 에 전체경로를 넣어준다 . strSrch = 146번 버스를 찾고자 하기 때문에 , 146을 넣어줬다
xmefile <- xmlParse(url)
è 웹에서 XML 파일 다운로드를 한다.
xmlRoot(xmefile)
è 다운 받은 XML파일에 루트엘리먼트 접근 or 출력을 한다
xmlRoot 결과값은 다음과 같다 .
<ServiceResult>
<comMsgHeader/>
<msgHeader>
<headerCd>0</headerCd>
<headerMsg>정상적으로 처리되었습니다.</headerMsg>
<itemCount>0</itemCount>
</msgHeader>
<msgBody>
<itemList>
<busRouteId>100100025</busRouteId>
<busRouteNm>146</busRouteNm>
<corpNm>삼화상운 02-936-6000</corpNm>
<edStationNm>강남역</edStationNm>
<firstBusTm>20181115040500</firstBusTm>
<firstLowTm> </firstLowTm>
<lastBusTm>20181115230000</lastBusTm>
<lastBusYn> </lastBusYn>
<lastLowTm>20150717230400</lastLowTm>
<length>57.2</length>
<routeType>3</routeType>
<stStationNm>상계주공7단지</stStationNm>
<term>10</term>
</itemList>
<itemList>
<busRouteId>241001340</busRouteId>
<busRouteNm>8146고양</busRouteNm>
<corpNm>경기</corpNm>
<edStationNm>동아방송대</edStationNm>
<firstBusTm>20181115062000</firstBusTm>
<firstLowTm> </firstLowTm>
<lastBusTm>20181115215000</lastBusTm>
<lastBusYn> </lastBusYn>
<lastLowTm> </lastLowTm>
<length>0</length>
<routeType>8</routeType>
<stStationNm>남부터미널</stStationNm>
<term>10</term>
</itemList>
</msgBody>
</ServiceResult>
위의 결과값을 보면 itemList 태그내에 값들이 존재하는 것을 알 수 있는데 ,
결과적으로 보면 우리는 itemList에 접근을 해야 하는 것을 알 수 있게 된다 .
그런데 , 8146 버스도 같이 검색되어 지는 걸 확인할 수 있다.
df <- xmlToDataFrame(getNodeSet(xmefile,"//itemList"))
è 우리는 itemList에 접근을 하며 동시에 DataFrame형태로 만들어 준다.
head(df)
head(df)결과값
busRouteId busRouteNm corpNm edStationNm firstBusTm firstLowTm lastBusTm
1 100100025 146 삼화상운 02-936-6000 강남역 20181115040500 20181115230000
2 241001340 8146고양 경기 동아방송대 20181115062000 20181115215000
lastBusYn lastLowTm length routeType stStationNm term
1 20150717230400 57.2 3 상계주공7단지 10
2 0 8 남부터미널 10
이쁘지는 않지만 DataFrame형태로 저장되어진 것을 알 수 있다.
우리는 146번 버스를 알고 싶은것이기 때문에 , 그외에 버스는 제외를 시켜 줄 것이다.
버스의 변수명을 보게 되면 busRouteNm으로 사용되는 것을 알 수 있다.
df_busRoute <- subset(df, busRouteNm==146)
df_busRoute 결과값
busRouteId busRouteNm corpNm edStationNm firstBusTm firstLowTm lastBusTm
1 100100025 146 삼화상운 02-936-6000 강남역 20181115040500 20181115230000
lastBusYn lastLowTm length routeType stStationNm term
1 20150717230400 57.2 3 상계주공7단지 10
이쁘게 146번에 대한 정보가 출력됬다.
이제는 가져온 버스에 대한 위치정보를 다뤄볼 것인데 ,
위치정보에 대해서 접근하기 위해서는 참고문서를 확인해 보아야 한다.
그런데 , 참고문서를 보면 버스위치에 대한 정보가 없다…. 완전 멘붕이였다…..
그래서 생각하게 된 것이 노선정보조회가 되니까 , 서울버스위지 조회도 되는 API가 있지 않을까를 생각하게 되었다.
그래서 찾게된 “버스위치정보조회 서비스” API !!
이 API 또한 신청을 해주고 인증키를 받았다는 가정하에 설명해 보겠다.
확실한 것이 아니였기 때문에 , 먼저 참고문서를 확인해 보았다.
아까 확인해본 busRouteid 기억이 나는가…
이 변수명은 서울정보 API 에서 노선ID에 해당했는데 ,
노선 ID로 차량들의 위치정보를 조회한다고 해서 검색해 보았더니….
노선 ID를 기반으로 차량위치를 알려주는 기능이 있다!!
그리고 확인이 되었으니 , 사용법을 알아야 할 것이다.
보면 정말 간단하다 .
busRouteid 를 검색해 주면 위와 같이 결과값들이 나온다
그런데 우리는 gpsX , gpsY가 필요하다 , 위도와 경도를 통해서 google_map을 불러올것이기 때문이다.
url2 <-"http://ws.bus.go.kr/api/rest/buspos/getBusPosByRtid?serviceKey=gH19buRy%2BiHenMjC6JkiwE6VEG1Mq1WChoYviIkZ3J5KsdshhG4N5MddOCsefPhYDOrfHH5ani2qhOR%2FiQRtpg%3D%3D&busRouteId=100100025"
그래서 나는 또한번의 API를 사용할 것인데 , url2에 첫번째 API에서 구한 busRouteid 값을 넣어준다.
xmefile <- xmlParse(url2)
è 이번에도 똑같이 XML 파일로 다운로드
xmlRoot(xmefile)
è XML 파일 루트엘리먼트에 접근
접근을 해서 출력해 보면 , 이것또한 itemList 내에 값들이 존재한다는 것을 알 수 있다.
고로 위에서와 똑같이 Node에 접근함과 동시에 DataFrame으로 저장시킬 것이다
df <- xmlToDataFrame(getNodeSet(xmefile,"//itemList"))
df 결과값
busType congetion dataTm fullSectDist gpsX gpsY isFullFlag islastyn isrunyn lastStTm
1 1 0 20181115221613 0.475 127.046991 37.662693 0 0 1 12428
2 1 0 20181115221559 0.593 127.055998 37.671144 0 0 1 11797
3 1 0 20181115221603 0.296 127.061269 37.651526 0 0 1 11266
4 1 0 20181115221612 0.685 127.070937 37.629642 0 0 1 10724
5 1 0 20181115221600 0.507 127.078336 37.607041 0 0 1 10123
6 1 0 20181115221602 0.219 127.079762 37.584937 0 0 1 9657
7 1 0 20181115221600 0.365 127.079961 37.573631 0 0 1 9433
8 1 0 20181115221614 0.501 127.065568 37.545112 0 0 1 8824
9 1 0 20181115221607 0.474 127.062441 37.509824 0 0 1 7962
10 1 0 20181115221600 0.588 127.04569 37.503614 0 0 1 7563
11 1 0 20181115221608 0.465 127.02326 37.499014 0 0 1 6869
12 1 0 20181115221602 0.739 127.027356 37.498137 0 0 1 6528
13 1 0 20181115221547 0.465 127.050462 37.504761 0 0 1 5798
14 1 0 20181115221526 0.59 127.062719 37.510408 0 0 1 5162
15 1 0 20181115221612 1.696 127.059378 37.533935 0 0 1 4807
16 1 0 20181115221603 0.355 127.069598 37.551704 0 0 1 4071
17 1 0 20181115221608 0.254 127.079686 37.580699 0 0 1 3450
18 1 0 20181115221610 0.362 127.078933 37.605036 0 0 1 2869
19 1 0 20181115221615 0.455 127.073161 37.625279 0 0 1 2408
20 1 0 20181115221613 0.474 127.066715 37.63963 0 0 1 2050
21 1 0 20181115221610 0.602 127.064613 37.644226 0 0 1 1868
22 1 0 20181115221602 0.325 127.062384 37.648775 0 0 1 1757
23 1 0 20181115221606 0.298 127.059002 37.660735 0 0 1 1405
24 1 0 20181115221521 0.483 127.055855 37.672926 0 0 1 1099
25 1 0 20181115221608 0.412 127.046154 37.669928 0 0 1 559
26 1 0 20181115221600 0.512 127.046512 37.663491 0 0 1 485
27 1 0 20181115221613 0.212 127.058359 37.661138 0 0 1 174
lastStnId nextStId nextStTm plainNo posX posY rtDist sectDist sectOrd
1 109000114 110000097 550 서울75사1380 204145.63539765115 462566.2380594765 57.2 0.116 5
2 110000098 110000265 809 서울75사1381 204939.68998904055 463504.5521238097 57.2 0.28 13
3 110000144 110000265 280 서울74사9628 205406.07747069895 461327.67241706 57.2 0.076 19
4 110000347 110000060 96 서울74사3547 206260.97104647642 458899.6349158217 57.2 0.544 25
5 106000011 106000013 92 서울74사1895 206916.10759999513 456391.9538511615 57.2 0.084 33
6 106000023 104000030 406 서울74사3566 207044.08935987312 453939.0244281525 57.2 0.081 39
7 106000027 104000030 194 서울74사4927 207062.73172955326 452684.3370501115 57.2 0.04 42
8 103000108 122000086 726 서울75사1564 205793.64597527092 449518.4196042619 57.2 0.263 49
9 122000095 122000115 388 서울74사1876 205519.94122295693 445602.1212387406 57.2 0.324 57
10 122000115 122000181 498 서울74사1882 204039.44526535223 444912.113812265 57.2 0.416 60
11 121000090 122000184 543 서울74사1892 202056.53883646545 444400.90151822753 57.2 0.22 66
12 121000096 122000184 203 서울75사1571 202418.7160162022 444303.6737007401 57.2 0.535 68
13 122000156 122000139 514 서울74사1874 204461.26876097269 445039.6179455365 57.2 0 73
14 122000094 104000127 565 서울74사3560 205544.47392486606 445666.94719788944 57.2 0 77
15 122000066 104000127 199 서울74사3526 205247.47534932615 448277.6783416732 57.2 1.427 81
16 104000142 106000016 1062 서울74사9650 206149.19878287354 450250.2299563093 57.2 0 86
17 106000026 106000016 441 서울74사4913 207037.776462721 453468.6992907822 57.2 0.067 93
18 106000014 110000315 817 서울74사4903 206969.00244541132 456169.48874929827 57.2 0.262 100
19 110000001 110000315 356 서울75사1583 206457.6410294542 458415.5904476489 57.2 0.305 106
20 110000315 110000155 458 서울74사1853 205887.5448999581 460007.80697735166 57.2 0.407 110
21 110000272 110000155 274 서울74사1596 205701.69378403295 460517.73132610833 57.2 0.242 112
22 110000157 110000155 162 서울74사3556 205504.66269258191 461022.43679212127 57.2 0.111 113
23 110000083 110000155 57 서울74사1887 205205.4054725255 462349.5415818379 57.2 0.079 117
24 110000099 110000155 59 서울75사6803 204926.95786166712 463702.30812030565 57.2 0 121
25 109000049 110000155 61 서울74사1878 204071.39842464254 463369.1293500974 57.2 0 127
26 109000051 110000155 60 서울75사1575 204103.3331757701 462654.77762219263 57.2 0.326 128
27 110000082 110000155 58 서울74사9647 205148.6494599342 462394.2302985168 57.2 0.095 131
sectionId stopFlag trnstnid vehId
1 109601335 0 121000088 110058320
2 110600685 0 121000088 110058287
3 110600298 1 121000088 110058251
4 110600340 0 121000088 110027369
5 106600023 1 121000088 110058296
6 106602150 1 121000088 110058363
7 104600498 1 121000088 110058019
8 103600314 0 121000088 110027269
9 122603676 0 121000088 110058411
10 122600736 0 121000088 110058226
11 121600802 0 121000088 110058512
12 121604114 0 121000088 110027273
13 122600631 1 121000088 110058330
14 122603587 0 121000088 110058286
15 104600449 0 121000088 110027118
16 104600258 1 121000088 110058189
17 106602152 1 121000088 110058227
18 106600093 0 121000088 110058325
19 110600029 0 121000088 110027180
20 110600352 0 121000088 110058322
21 110600356 0 121000088 110058328
22 110600313 0 121000088 110027160
23 110600705 1 121000088 110058004
24 110600393 0 121000088 110058190
25 109600398 1 121000088 110058527
26 109601726 0 121000088 110027390
27 110600689 0 121000088 110058099
데이터프레임 형태로 만들었다 .
이제 우리는 위도와 경도를 가져올 것이다.
df 변수명을 지정해 주었기 때문에 , 접근또한 df에 접근을 해서 gpsX , gpsY 의 값을 빼오자 .
gpsX <- as.numeric(as.character(df$gpsX))
gpsY <- as.numeric(as.character(df$gpsY))
각각의 결과값들을 보면 다음과 같다 .
> gpsX
[1] 127.0470 127.0560 127.0613 127.0709 127.0783 127.0798 127.0800 127.0656 127.0624 127.0457 127.0233
[12] 127.0274 127.0505 127.0627 127.0594 127.0696 127.0797 127.0789 127.0732 127.0667 127.0646 127.0624
[23] 127.0590 127.0559 127.0462 127.0465 127.0584
> gpsY
[1] 37.66269 37.67114 37.65153 37.62964 37.60704 37.58494 37.57363 37.54511 37.50982 37.50361 37.49901
[12] 37.49814 37.50476 37.51041 37.53393 37.55170 37.58070 37.60504 37.62528 37.63963 37.64423 37.64878
[23] 37.66074 37.67293 37.66993 37.66349 37.66114
위 결과값들을 보면 , 위도와 경도 형태로 나오는 것을 알 수 있다 .
범위는 -180 ~ 180 의 형태를 나타낸다 .
이제 위도와 경도를 하나의 새로운 데이터 프레임으로 생성을 해준다 .
gc <-data.frame(lon=gpsX, lat=gpsY)
è 경도 , 위도 설정
gc 의 결과값
1 127.0470 37.66269
2 127.0560 37.67114
3 127.0613 37.65153
4 127.0709 37.62964
5 127.0783 37.60704
6 127.0798 37.58494
7 127.0800 37.57363
8 127.0656 37.54511
9 127.0624 37.50982
10 127.0457 37.50361
11 127.0233 37.49901
12 127.0274 37.49814
13 127.0505 37.50476
14 127.0627 37.51041
15 127.0594 37.53393
16 127.0696 37.55170
17 127.0797 37.58070
18 127.0789 37.60504
19 127.0732 37.62528
20 127.0667 37.63963
21 127.0646 37.64423
22 127.0624 37.64878
23 127.0590 37.66074
24 127.0559 37.67293
25 127.0462 37.66993
26 127.0465 37.66349
27 127.0584 37.66114
결과값들을 가져오고 보니 , 생각보다 많다…
10번째 까지의 값들만 다뤄보자
가감히 잘라준다.
gc1 <- head(gc, n=10)
gc1의 결과값
> gc1 <- head(gc, n=10)
> gc1
lon lat
1 127.0470 37.66269
2 127.0560 37.67114
3 127.0613 37.65153
4 127.0709 37.62964
5 127.0783 37.60704
6 127.0798 37.58494
7 127.0800 37.57363
8 127.0656 37.54511
9 127.0624 37.50982
10 127.0457 37.50361
10 번째 까지 출력이 잘 된 것을 확인 할 수 있다.
이제 우리는 map에 표현해 주기 위한 범위를 지정해 줄 것인데,
경도 위도 각각의 평균값을 cen이라는 변수에 저장 시켜 준다
cen <- c(mean(gc1$lon), mean(gc1$lat))
cen 결과값
> cen <- c(mean(gc1$lon), mean(gc1$lat))
> cen
[1] 127.06470 37.59392
경도와 위도의 평균값은 이렇구나 하고 넘어간다.
## 여기서부터 중요하다 , 개인적으로 이부분이 조금 의아했다 . 왜냐하면 한 한달전?? 그때 똑같이 했었는데 , 실행이 됬는데 , google_map api를 못불러 오는 것이다 … 그래서 알게 된 것을 써보자 한다 .
# https://github.com/dkahle/ggmap/issues/51
# https://code.i-harness.com/ko-kr/q/31b461
# 참고한 사이트
결과적으로 얘기를 해보자면 , google_map api를 설정해 주어야 하며 , 그 api에 해당하는 인증키를 받아서 접근해서 사용해야 한다는 것이다….
어렵다 … 그림을 통해서 이해해 보자 .
먼저 구글에 로그인하고 , google Cloud Platform 관리에 들어간다.
들어가서 새 프로젝트를 만들어 준다 .
새 프로젝트를 만드면 , Google 지도가 보일 것인데 , 혹은 아무것도 없을 수도 있다.
그러면 검색창에 Map Static API 를 검색해서 활성화를 클릭한다 .
활성화 클릭후 API 인증키를 받는다 .
인증키를 받았으면 이것을 사용해야 하는데
위 그림을 보자 , Static map 에 대한 Document이다 .
보면 Key = “ Your_API_KEY” 라는게 보일 것이다
이부분을 get_google 속성에 추가해 주면 된다 .
key <- "xxxxxxxxx"
è 나의 API 인증키 이다 . 보안상 가렸다.
map <- get_googlemap(center = cen , maptype = "roadmap" , zoom=11 , markers = gc1 , key = key)
ggmap(map)
최종 결과값
https://github.com/dkahle/ggmap/issues/51
è Get_googlemap Solution
그런데 하긴 했는데 , 과연 146번의 위치경로가 맞을것인가…라는 생각을 하게되었다.
위치경로를 어떻게 알것인가??
실시간 위치정보이기 때문에 , 맨 아래 버스와 끝 버스의 경로를 통해 추측해 볼 수 있을것같다.
네이버 지도를 활용해서 146번의 버스 경로를 찾아 보았다.
다음 결과를 얻을 수 있었는데 , 반포를 시작으로 의정부 가기전까지의 경로를 확인할 수 있었다.
R에서의 결과와 대충 맞아 떨어진다 …ㅎㅎ 신기하다 !!
'학부공부 > 데이터마이닝과통계' 카테고리의 다른 글
Corpus --> VCorpus (2) | 2018.11.18 |
---|---|
논문제목+논문저자+논문발간일 크롤링 / wordcloud2 (5) | 2018.11.18 |
web_crawling + wordCloud (0) | 2018.11.15 |
동아신문 스크랩핑 (0) | 2018.11.14 |
나이키 사이트 크롤링 (0) | 2018.11.10 |
#IT #먹방 #전자기기 #일상
#개발 #일상