読者です 読者をやめる 読者になる 読者になる

次元の海で溺れる

Rとデータ解析と統計手法たちとわたし

【leaflet,jsonlite】家を探しのススメ~路線が分からない編~

あけましておめでとうございます。
新年早々水道を止められかけるなどしましたが元気です。

今回のテーマ

土地勘が無いところの家探しをすると仮定します。
世の中には様々な不動産サイトがありますが、
土地勘が無いともうなんだか全部どうでもよくなってきます。
そもそも住みたいエリアも分からんそもそも知らん。となってきます。

せめてエリアを決めるために以下を仮定して、なんとなく便利げなエリアを把握しよう、というのが
今回の目標です。

  • 目的地は市ヶ谷 (特に意味はない)
  • 乗り換えたくない
  • 駅前に住みたい (300M以内)

ではやってみる。

データ

各種路線情報取得のため、今回はこちらのAPIを使用させて頂きました。
データはこれだけ。
www.ekidata.jp

市ヶ谷駅に乗り入れている路線は

の4つらしい。なるほどわからん。

パッケージ

library(leaflet)
library(dplyr)
library(magrittr)
library(jsonlite)
library(knitr)

APIを叩いて路線情報を取得

#総武線 11313
#東京メトロ有楽町線 28006
#都営新宿線 99304
#東京メトロ南北線 28009

url<-c("http://www.ekidata.jp/api/l/11313.json",
       "http://www.ekidata.jp/api/l/28006.json",
       "http://www.ekidata.jp/api/l/99304.json",
       "http://www.ekidata.jp/api/l/28009.json")

for(i in 1:length(url)){
readLines(url[i],encoding = "UTF-8")[3] %>% 
    gsub("xml.data = ","",.,fixed=TRUE) %>% 
    fromJSON()->JSON
  switch(i,
        "1"= JSON->soubu_line,
        "2"= JSON->yurakutyo_line,
        "3"= JSON->sinzyuku_line,
        "4"= JSON->nanboku_line)
}

4路線一気にいきたかったけどそうもいかなかった...
いったん路線別に取得したものは、fromJSON()でこんな感じのリストになっています。

> soubu_line

$line_cd
[1] 11313

$line_name
[1] "JR中央・総武線"

$line_lon
[1] 139.8372

$line_lat
[1] 35.70164

$line_zoom
[1] 10

$station_l
   station_cd station_g_cd station_name      lon
1     1131301      1131105         三鷹 139.5603
2     1131302      1131104       吉祥寺 139.5798
3     1131303      1131218       西荻窪 139.5994
4     1131304      1131217         荻窪 139.6201
5     1131305      1131216     阿佐ケ谷 139.6359
6     1131306      1131215       高円寺 139.6497
7     1131307      1131214         中野 139.6658
[省略]

「station_l」に入っているdata.frameが目的の路線情報なので
ここを抽出して4路線分くっつけておきます。

前処理

station_lには路線自体の情報が含まれていないので、
後から使うためにstation_cdの前5桁をline_cdとして切り出し、それをもとに路線名称をくっつけます。
これで後からFilter出来るはず。

#市ヶ谷駅
ichigaya <- c("139.736642","35.691295")

#4路線を統合、路線CDが失われるので、station_cdの前5桁を取得
line<-dplyr::bind_rows(soubu_line$station_l,yurakutyo_line$station_l,sinzyuku_line$station_l,nanboku_line$station_l) %>%
  dplyr::mutate(line_cd=as.character(substr(station_cd,1,5)))

#路線名マスタ
line_cd_master<-data.frame(line_cd=c("11313","28006","99304","28009"),
                           line_name=c("総武線","有楽町線","新宿線","南北線"),stringsAsFactors=FALSE)

#路線名をJOIN
line<-dplyr::left_join(line,line_cd_master,by="line_cd")
line$line_name<-as.factor(line$line_name)

#総武線 11313
#東京メトロ有楽町線 28006
#都営新宿線 99304
#東京メトロ南北線 28009

#色パレット関数作成
colpal<-colorFactor(c("tomato","RoyalBlue","MediumSeaGreen","Firebrick"),domain=c("総武線","有楽町線","新宿線","南北線"))

完成後はこんな感じ。

> kable(head(line),format="markdown")
station_cd station_g_cd station_name lon lat line_cd line_name
----------: ------------: :------------ --------: --------: :------- :---------
1131301 1131105 三鷹 139.5603 35.70268 11313 総武線
1131302 1131104 吉祥寺 139.5798 35.70312 11313 総武線
1131303 1131218 西荻窪 139.5994 35.70384 11313 総武線
1131304 1131217 荻窪 139.6201 35.70452 11313 総武線
1131305 1131216 阿佐ケ谷 139.6359 35.70482 11313 総武線
1131306 1131215 高円寺 139.6497 35.70533 11313 総武線

描いちゃう

leaflet(line) %>% 
    addTiles() %>% 
    setView(lng=ichigaya[1],lat=ichigaya[2],zoom=12) %>%
    addMarkers(lng=ichigaya[1],lat=ichigaya[2]) %>%
    addPolylines(lng=~lon,lat=~lat,color=~colpal(line_name),weight=3,data=dplyr::filter(.data=line,line_name=="総武線"),group="総武線") %>%
    addCircles(lng=~lon,lat=~lat,radius=300,color=~colpal(line_name),weight=5,data=dplyr::filter(.data=line,line_name=="総武線"),group="総武線") %>%
    addPolylines(lng=~lon,lat=~lat,color=~colpal(line_name),weight=3,data=dplyr::filter(.data=line,line_name=="有楽町線"),group="有楽町線") %>%
    addCircles(lng=~lon,lat=~lat,radius=300,color=~colpal(line_name),weight=5,data=dplyr::filter(.data=line,line_name=="有楽町線"),group="有楽町線") %>%
    addPolylines(lng=~lon,lat=~lat,color=~colpal(line_name),weight=3,data=dplyr::filter(.data=line,line_name=="新宿線"),group="新宿線") %>%
    addCircles(lng=~lon,lat=~lat,radius=300,color=~colpal(line_name),weight=5,data=dplyr::filter(.data=line,line_name=="新宿線"),group="新宿線") %>%
    addPolylines(lng=~lon,lat=~lat,color=~colpal(line_name),weight=3,data=dplyr::filter(.data=line,line_name=="南北線"),group="南北線") %>%
    addCircles(lng=~lon,lat=~lat,radius=300,color=~colpal(line_name),weight=5,data=dplyr::filter(.data=line,line_name=="南北線"),group="南北線") %>%
    addLegend(position = "topright", pal = colpal, value = ~line_name, title = "Line") %>% 
    addLayersControl(overlayGroups = c("総武線","有楽町線","新宿線","南北線"),options = layersControlOptions(collapsed = FALSE))

f:id:WAFkw:20170110005037p:plain

事前に、colorFactor()で各路線をdomainとして定義しておき、
leaflet内では路線ごとにFilterして、それぞれ線を引いたり、駅に円を置いたりする。

addCircles()内のradius引数はm単位なので、今回の「300m」指定に合わせる。
これで駅から300m範囲に円が作れる。

後はaddLayersControl()で各路線を表示ON/OFF出来るようにすればOK。

都営新宿線南北線~とか
f:id:WAFkw:20170110005654p:plain

総武線と有楽町線~とか
f:id:WAFkw:20170110005803p:plain

チェックをポチポチすればいいので便利。便利だ!!!

おわり

あとはこれに各駅の乗降者数とかを乗っければ混む駅とかが分かる。はず。
平均家賃はスクレイピング要りそうでめんどくさいからやめよう。

後はもうすこし情報載せて駅候補決めて、
不動産へ行って「ぼくこの円の中に住みたいんだよね!」って言えばOK。

.......なんで目的地市ヶ谷にしたんだろう.....謎....

参考

addLayersContoroll()を使ってみたくて書いた記事ですが
冷静に考えたらすでにぞうさん先生が大分以前に台風プロットで使ってらっしゃいました。
分かりやすい.....

leafletではじめるRによる地図プロット

P.S

年末色々ありすぎて数々の不義理を重ねました。
謝罪参りしなきゃいけないことが多すぎる。水道局とか水道局とか。

Japan.Rに行けなかったのを今でも引きずっているので
誰か居酒屋.RでLT聞いてやってください。