この資料に至るまでの経緯はこちら

まずは妹島和世周辺の師弟関係をざっと可視化

library("DiagrammeR")
grViz("
      digraph G{
        graph [rankdir = LR]

        // nodeの属性を指定
        node [shape = oval,
              color = black]
        菊竹清訓; 伊東豊雄

        node [shape = box,
              color = red]
        妹島和世
        
        // 構造を指定
        菊竹清訓 -> 伊東豊雄 -> 妹島和世
      }",
      width=800, height=200)


妹島和世の都内建築物リストを読み込む

library("data.table")
data_sejima <- fread("https://raw.githubusercontent.com/dichika/mydata/master/sejima.csv",
                        data.table=FALSE)












DTで表を可視化

library("DT")
datatable(data_sejima)








途中休憩のブルーボトルコーヒーを追加

library("dplyr")
data_sejima <- bind_rows(data_sejima,
                         data_frame(year = 2015,
                                    name = "ブルーボトルコーヒー",
                                    address = "東京都港区南青山3-13-14",
                                    memo = "お茶")
)












スタート地点の東京駅を加える

data_sejima <- bind_rows(data_sejima,
                         data_frame(year = 1914,
                                    name = "東京駅",
                                    address = "千代田区丸の内1-9-1",
                                    memo = "スタート地点")
)












住所データから緯度経度を取得

# ジオコーディング

getLocation <- function(x){
  require("httr")
  tmp <- content(GET(x), "parsed")
  res <- data_frame(
    lat=tmp$results[[1]]$geometry$location$lat,
    lng=tmp$results[[1]]$geometry$location$lng
    )
}

adds <- data_sejima$address
qs <- paste0("http://maps.googleapis.com/maps/api/geocode/json?address=", adds)

locs <- NULL
for(q in qs){
  locs <- bind_rows(locs, getLocation(q))
  Sys.sleep(1) # 使用制限にひっかからないように1秒待つ
  }
data_sejima <- bind_cols(data_sejima, locs)












leafletでいったん可視化する。

library("leaflet")
leaflet() %>% 
  addCircleMarkers(data =data_sejima,
             lat = ~lat, 
             lng = ~lng,
             radius = 10) %>%
  addPopups(data=data_sejima,
             lat= ~lat, 
             lng= ~lng,
             popup=data_sejima$name,
            options=popupOptions(minWidth=10)
             ) %>% 
  addTiles()











—-

TSPで経路探索をする

library("TSP")

data_dist <- ETSP(data_sejima[,c("lat","lng")])

res <- NULL
for(m in c("identity", "random",
           #nearest_insertion","cheapest_insertion","farthest_insertion","arbitrary_insertion"", 
           "nn", "repetitive_nn", "two_opt")){
  tmp <- solve_TSP(data_dist, 
                   method = m,
                   control=list(start=9)) # start地点の行を指定
  res <- bind_rows(res, data_frame(method=attr(tmp, "method"),
                                   tour_length=attr(tmp, "tour_length")))
}












経路探索の結果を確認する

datatable(res)












nnの結果を使って再計算

res_nn <- solve_TSP(data_dist,
                    method = "nn",
                    control=list(start=9))
data_order <- as.integer(res_nn) # 回る順番
data_sejima <- data_sejima[data_order,] # 並べ替え












経路データの作成

points_to_line <- function(data, long, lat, id_field = NULL, sort_field = NULL) {
  require("sp")
  require("maptools")
  # Convert to SpatialPointsDataFrame
  coordinates(data) <- c(long, lat)
  
  # If there is a sort field...
  if (!is.null(sort_field)) {
    if (!is.null(id_field)) {
      data <- data[order(data[[id_field]], data[[sort_field]]), ]
    } else {
      data <- data[order(data[[sort_field]]), ]
    }
  }
  
  # If there is only one path...
  if (is.null(id_field)) {
    
    lines <- SpatialLines(list(Lines(list(Line(data)), "id")))
    
    return(lines)
    
    # Now, if we have multiple lines...
  } else if (!is.null(id_field)) {  
    
    # Split into a list by ID field
    paths <- sp::split(data, data[[id_field]])
    
    sp_lines <- SpatialLines(list(Lines(list(Line(paths[[1]])), "line1")))
    
    # I like for loops, what can I say...
    for (p in 2:length(paths)) {
      id <- paste0("line", as.character(p))
      l <- SpatialLines(list(Lines(list(Line(paths[[p]])), id)))
      sp_lines <- spRbind(sp_lines, l)
    }
    
    return(sp_lines)
  }
}












経路を可視化して完成

library("leaflet")

leaflet(data = data_sejima) %>% 
  addCircleMarkers(lat = ~lat, 
                   lng = ~lng,
                   popup= ~name,
                   radius = 10) %>%
  addPolylines(lat = ~lat,
               lng = ~lng) %>% 
  addPopups(data=data_sejima[range(seq(nrow(data_sejima))),],
            lat= ~lat, 
            lng= ~lng,
            popup=data_sejima$name[range(seq(nrow(data_sejima)))],
            options=popupOptions(minWidth=10)
  ) %>% 
  addTiles()












つまづくポイント













参考資料