SHPファイルの内容をShiny及びleafletを使って動的コロプレス図として作動させる


QGISユーザなどSHPファイルをオフラインで編集するユーザには、オンラインで動的地図を作動させたいという要望があると思われる。
Javaにあるleafletというパッケージは、動的地図を作動させる優れたプログラムらしいが、Javaはよくわからないので同じ機能を有して記法が少しわかるRのShniyパッケージを用いて、leafletを作動させてみることにしたい。
以下、ソースコードを挙げておくので、Shinyのパッケージが動く方は、試してみてほしい。

多くのShinyのleafletに関するソースコードサンプルが、コロプレスの表示用データフレームを別途に準備して読み込ませる方法をとっているが、ここではdbfに欲しいデータが一式そろったSHPファイルをアップロードする方法をとった。メリットは、ポリゴン間のズレが確認されないことや、上げるデータ数が少なくてすむことなどだろうか。

意外とこの要望を満たすソースコードサンプルがなかったので、今後、どなたか参考にされることを念頭にアップロードしておく。

なお、Shinyコマンドを格納するディレクトリの下にデータ用のディレクトリが必要なことになるが、こうした細かい手続きは別途、Shinyを確認してほしい。

###動作イメージ
![スクリーンショット 2020-03-21 14.19.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504024/56683ca9-85c7-3165-3356-0cb9caf77939.png)




```sample.r
#このソースコードでは、SHPファイルに格納されたデータのみで、コロプレス図に使用するデータを動的に変更し、ポップアップ表示に格納されたデータを表示する地図アプリケーションを動かす。

#shinyでserverとuiを分けて設計する場合は、以下、global.rのファイルの中身に相当するのが下記のソースコード

#読み込みパッケージの一覧
library(shiny)
library(shinydashboard)
library(ggmap)
library(leaflet)
library(dplyr)
library(rgdal)
library(maptools)
library(rmapshaper)
library(tidyverse)

#ここではソースコードを入れているディレクトリの下に、データ用にshapeという名前のディレクトリを作っている。下記shape <-はそのディレクトリからSHPファイルを読み取るコードになる。rgdal:readOGRで統計データが格納されたSHPファイルを読み取る。layer変数でファイル名を指定する。以下、readOGRのヘルプを参照。なお、shape_tempは架空のファイルなので、各自実データを入れてほしい。

shape <- readOGR(dsn = "./shape",
                 layer = "shape_temp", encoding = "shift-JIS", stringsAsFactors = FALSE)

#ここで、コロプレス図の基礎データを変更するためにshapeに格納されているデータをデータフレーム型にしてshape_dataという新たな変数で保存する。多くの参考ソースコードでは、地図データとは別にdata.frameを準備する方法を示しているが、SHPファイルを直に編集しているQGISソフトなどを利用しているユーザは別個にデータを用意することは面倒なケースもあると思われる。また、47都道府県レベルならまだしも、市区町村単位のデータの場合は、ソフト上のデータの突合が不整合なケースがあるので、SHPファイルから素直に読ませたほうが確実という気がする。
shape_data <- as.data.frame(shape)

#カーソルを地図の固有のポリゴンに合わせた時に表示されるラベルをsprintf関数で定義する。記述方法の詳細は、sprintf関数のヘルプを参照されたいが、ダブルクオーテーション（”）で囲まれている部分が、ポップアップ画面の表示内容になる。文字は%s、数値は%gを入力して改行は<br>タグを使用する。協調文字は<strong></strong>タグを使う。各タグの方法は、関数ヘルプを参照。ちなみに、1行目にポリゴン該当箇所の名前の文字列、2列めは「データ1　呼び出し数字　（単位）」という表示になる。ダブルクオーテーション以下、コンマ（,）以下で上の各項目に表示させるデータを地図データから呼び出す。最後にhtmlに渡してラベル変数に格納する。
labels <- sprintf(
  						  "<strong>%s</strong><br/>
   						データ1　%g （単位）<br>",
    					shape$cityname,
    					shape$data1
						) %>% 
   				 lapply(htmltools::HTML) 

#データフレーム内の指定するデータを選択するためのリスト。data1、2などシングルクォーテーションで囲まれている部分はSHPファイルのdbfに格納されている各地域の列データの列名を指定する。これをdata_domainという変数に格納する。html上での表示名を変更したい場合は、'表示名'='data'というふうに記述する。このリストをui側で動的に受け取り、server側にインプットして、コロプレスの受け取り数値を動的に変更させる。
data_domain <- c('data1','data2','data3')

#global.rに相当する部分はここまでとなる。以下、ui.rに相当箇所。

#ui.rとはつまり実際のブラウザなどで表示される際のページ設計及び、ページ内に動的に挿入される(output）オブジェクトの位置や、ユーザが利用した際に選択したオブジェクトをserver.rにわたす（imput）フォームやその際の値などを設定している。ここでは、かなりかんたんなページ構成にしているため、内容は最低限である。
ui <- 
    ui <- 
        fluidPage(
          titlePanel("タイトル"),
          mainPanel(
        		  leafletOutput("map1"),
                  selectInput ('data', label = "データ選択", choices = data_domain)#ここでglobal.rで指定したdata_domainのリストがインプットとして受け取られ、サーバに送られる。
                           )
                        )

#ここからサーバ、受け取ったデータを編集したり読み込んだりしてui側に渡す設定となる。
server <-
   function(input, output, session) {
    
     output$map1 <- renderLeaflet({
        
        pal <- colorBin("Spectral",bins = 5,domain = shape_data[, input$data], reverse = F)#これはコロプレス図の色調を決めるためのpal変数の指定。addPolygons関数のfillColor変数で動的にコロプレスに参照されるデータを変更するためにしている。なお、有効データ数の関係でcolorQuintelなど四分位数などに分割するものが使えない場合があるので各自研究してほしい。

#leaflet関数で地図データを読み込み、ハイプでそれ以外の処理をつないでいる。addTiles（）でオーバレイに使用する基礎地図を指定するが、空欄であるとOpenStreetMapが自動的に指定される。重要なのは、コロプレス図を指定するためにポリゴンを表示させるaddPolygons関数のfillColor変数で、ここでデータフレームに変換されているshapeの情報、shape_dataからuiで受け取ったデータを逐次挿入してコロプレスを書き直す指示を与えている。        
        leaflet(shape) %>%
            
            addTiles() %>%
            
            addPolygons(color = "#444444", weight = 1, smoothFactor = 0.5,
                        opacity = 0.8, fillOpacity = 0.5,
                        fillColor = ~pal(shape_data[, input$data]),
                        highlightOptions = highlightOptions(color = "black", weight = 2,
                                                            bringToFront = TRUE),

#以下、labelに続く箇所でポリゴンにマウスをクロスオーバーさせた際に、globalで指定したlabelsデータを反映する命令を与えている。                        
                        label = labels,
                        labelOptions = labelOptions(style = list("font-weight" = "normal", 
                                                                 padding = "3px 8px"),
                                                    textsize = "10px",
                                                    direction = "auto")) %>%
#以下、addLegendでコロプレス図の凡例を表示させている。            
            addLegend(pal = pal,values = ~shape_data[, input$data], title=input$data)
        
        
    })}#以上、output$map1以下に記載されている内容がoutput$map変数に格納されたので、この変数がui側に渡されることで表示されることになる。


shinyApp(ui, server)
```