r advent calendar201320140102分

11
オープンデータとR ggmapTSPパッケージを使って 施設巡回経路を考えてみる R Advent Calendar 2013 2014/1/2かわはら

Upload: hiroki84

Post on 02-Jul-2015

839 views

Category:

Technology


0 download

DESCRIPTION

R Advent Calendar 2013(http://atnd.org/events/45043) 2014/1/2分として作成したものです。 オープンデータとR、をテーマとして、今回は流山市のオープンデータを利用してみました。(http://www.city.nagareyama.chiba.jp/10763/index.html)

TRANSCRIPT

Page 1: R advent calendar201320140102分

オープンデータとR

ggmapとTSPパッケージを使って 施設巡回経路を考えてみる

R Advent Calendar 2013 2014/1/2分

かわはら

Page 2: R advent calendar201320140102分

概要

突然ですが、公園を巡回する経路を考えてみます。流山市のオープンデータとして公開されているデータとGoogleMapを利用して、公園を効率的にまわる経路を表示してみました。 「オープンデータとR」というテーマで何かやってみることないかな、 と考え、前回(http://www.slideshare.net/hiroki84/rlinked-open-data-in-29087495)はgoogleVisパッケージを使った施設の可視化だったので、今回はggmapパッケージを使った可視化とルートの検出をテーマにして簡単にまとめてみました。

Page 3: R advent calendar201320140102分

1. データの取得、抽出、確認

流山市のオープンデータトライアルHPから、「平和台」の公園データを使います。CVSファイルを読み込み、対象データを抽出します。

http://www.city.nagareyama.chiba.jp/10763/index.html

#CSVファイルのURL url.parks <- "http://www.city.nagareyama.chiba.jp/dbps_data/_material_/localhost/shisetsu_kouen.csv" #公園データの取得 parks <- read.csv(url.parks) #平和台が付く公園の収集 parks.selected <- parks[grep("平和台", parks$名称), 1:7]

Page 4: R advent calendar201320140102分

1. データの取得、抽出、確認

抽出したデータの内容を確認します。

• 公園は全部で10ヶ所 • 今回は名称、緯度、経度を使用

Page 5: R advent calendar201320140102分

1. データの取得、抽出、確認

ggmapパッケージを利用してGoogle Map(*)上にプロットします。まずは、周辺地図の表示です。

#ggmapの利用 install.packages("ggmap"); library(ggmap) #経度緯度情報のまとめ lat <- parks.selected$緯度 lon <- parks.selected$経度 loc <- c(min(lon), min(lat), max(lon), max(lat)) #結果のプロット M <- ggmap(get_map(location = loc, zoom=15, source = "google")) + xlab("") + ylab("")

*オープンデータ関連なのでOpenStreetMapを考えたましたが、 ggmap(…, source=“osm”)がうまくいかずGoogle Mapを使いました。

Page 6: R advent calendar201320140102分

1. データの取得、抽出、確認

取得データをもとに公園をプロット(●)します。

MP <- M + geom_point(data = parks.selected, aes(x=経度, y=緯度), size=7, colour="red")

しかし、いくつかの公園は、実際にHPで紹介さ

れている位置とは違う位置にあるようです(下記、平和台1号公園)。左図のプロットはとりあえずの目安と考えて下さい。

HPの緯度経度からのプロット

HPで紹介されている位置

Page 7: R advent calendar201320140102分

2. データの加工

「平和台」の公園データを同じ箇所を通らないように、最短で巡回する経路を考えてみます。まず、各公園間の移動時間を計算します。

1 2 3 4 5 6 7 8 9 10

1 0.0 5.3 5.8 0.0 5.4 3.0 4.9 5.1 2.2 11.2

2 5.3 0.0 6.1 5.7 11.1 4.5 8.9 9.3 4.8 6.5

3 5.8 6.1 0.0 5.2 8.0 5.5 9.2 9.5 3.2 10.4

4 0.0 5.7 5.2 0.0 5.4 3.0 4.9 5.1 2.2 11.2

5 5.4 11.1 8.0 5.4 0.0 7.1 5.2 4.1 6.0 16.0

6 3.0 4.5 5.5 3.0 7.1 0.0 5.1 5.5 2.8 9.5

7 4.9 8.9 9.2 4.9 5.2 5.1 0.0 2.9 6.3 11.5

8 5.1 9.3 9.5 5.1 4.1 5.5 2.9 0.0 6.2 13.4

9 2.2 4.8 3.2 2.2 6.0 2.8 6.3 6.2 0.0 10.6

10 11.2 6.5 10.4 11.2 16.0 9.5 11.5 13.4 10.6 0.0

#徒歩で移動する場合 travelmode = "walking" #nr x nrの時間行列と距離行列の作成 nr <- nrow(parks.selected) time <- matrix(0, nr, nr) distance <- matrix(0, nr, nr) for (i in 1:nr){ parks.selected.i <- parks.selected[i,] loc.i <- c(parks.selected.i$経度, parks.selected.i$緯度) for (j in (i+1):nr){ parks.selected.j <- parks.selected[j,] loc.j <- c(parks.selected.j$経度, parks.selected.j$緯度) route.ij <- route(loc.i, loc.j, mode=travelmode, structure="route") #時間行列と距離行列に代入 time[i, j] = time[j, i] <- sum(route.ij$minutes, na.rm=T) distance[i, j] = distance[j, i] <- sum(route.ij$km, na.rm=T) } }

各公園(1~10)間の移動時間を、route関数で計算した結果。単位はmin。徒歩移動とした。車移動の場合は、travelmode=“driving”

Page 8: R advent calendar201320140102分

2. データの加工

10ヶ所の公園を1回ずつ経由するルートを、TSPパッケージを使って計算します。

install.packages("TSP"); library(TSP) ans <- solve_TSP(TSP(time))

• TSP関数で、距離の行列をTSP形式に変換 TSP: symmetric traveling salesperson problem(セールスマン巡回問題) • solve_TSP関数で、最短経路を求める これだけです。。。 solve_TSP(x, method, control)のように使います。methodは指定が無ければ、最近挿入法が採用されます。

Page 9: R advent calendar201320140102分

2. データの加工

10ヶ所の公園を1回ずつ経由するルートを、TSPパッケージを使って計算します。

install.packages("TSP"); library(TSP) ans <- solve_TSP(TSP(time))

• TSP関数で、距離の行列をTSP形式に変換 TSP: symmetric traveling salesperson problem(セールスマン巡回問題) • solve_TSP関数で、最短経路を求める これだけです。。。 solve_TSP(x, method, control)のように使います。methodは指定が無ければ、最近挿入法が採用されます。

この順で公園をまわっていけばいいということらしい。

Page 10: R advent calendar201320140102分

3. データの表示

公園の巡回順路、所用時間、距離をプロットしていきます。

#経路のプロット。ans[k]番目からans[k+1]番目の公園への移動経路のプロット for (k in 1:(nr-1)){ h1 <- ans[k]; h2 <- ans[k+1] route <- na.omit(route(c(lon[h1], lat[h1]), c(lon[h2], lat[h2]), mode=travelmode, structure="route")) #与えられた座標をそのまま使用すると正しく表示されないことがあるので、 #移動経路の始点(最後にまわる公園については終点)を公園の位置とした。 M <- M + geom_point(data=route[1,], aes(x=lon, y=lat), size=10, colour="red", alpha=0.75) M <- M + geom_text(data=route[1,], aes(x=lon, y=lat), label=k, colour="white") M <- M + geom_text(data=route[1,], aes(x=lon, y=lat+0.0005), label=parks.selected$名称[h1], colour=“red”, size=4) M <- M + geom_path(data=route, aes(x=lon, y=lat), size=1.5, colour="red", alpha=0.75) M <- M + geom_text(data=route, aes(x=mean(lon), y=mean(lat)), label=paste(sprintf("%3.1f", sum(route$min)), "min, ", sprintf("%3.1f", sum(route$km)), "km", sep=""), colour="white", size=4) if (nrow(route)<2){ lonlat <- data.frame(lon=lon[c(h1, h2)], lat=lat[c(h1, h2)]) M <- M + geom_path(data=lonlat, aes(x=lon, y=lat), size=0.75, colour="red", alpha=0.75, type="dotted") } } M <- M + geom_point(data=route[nrow(route),], aes(x=lon, y=lat), size=10, colour="red", alpha=0.75) M <- M + geom_text(data=route[nrow(route),], aes(x=lon, y=lat), label=k+1, colour="white") M <- M + geom_text(data=route[nrow(route),], aes(x=lon, y=lat+0.0015), label=parks.selected$名称[h1], colour="red", size=4)

Page 11: R advent calendar201320140102分

3. データの表示

プロットの結果です。ちょっとごちゃごちゃして見にくくなってしまいました。。。 ●: 公園(数値は巡回順) 赤字: 公園名 白字: 公園間移動距離・時間

以上です