日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【Shiny】基于R-Shiny制作地图App(百度地图)

發(fā)布時(shí)間:2024/3/26 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Shiny】基于R-Shiny制作地图App(百度地图) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

估計(jì)每個(gè)愛(ài)好編程的都想某天可以開發(fā)出一個(gè)專屬于自己的軟件or應(yīng)用,在下也是。然而由于當(dāng)初入門編程的時(shí)候偷懶特地避開了那些以開發(fā)為目的源代碼級(jí)的語(yǔ)言(比如說(shuō)java,C和C++)而選擇了R,我離這個(gè)目標(biāo)估計(jì)是越走越遠(yuǎn)了。雖然R語(yǔ)言擁有自己的GUI開發(fā)工具,但是由于不能封裝所以只能給留給自己看。不過(guò)好在Rstudio公司開發(fā)的Shiny包可以基于R語(yǔ)言制作web端的APP,依托于互聯(lián)網(wǎng),算是間接實(shí)現(xiàn)了封裝并傳播的功能。不過(guò)shiny所實(shí)現(xiàn)的web app只能實(shí)現(xiàn)些比較簡(jiǎn)單的功能,設(shè)計(jì)出來(lái)的初衷是為了在結(jié)果展示的時(shí)候作為Data Product來(lái)保證展示的過(guò)程更流暢更直觀。所以想做游戲的還是安心學(xué)java吧。這次想分享的是我自己閑著沒(méi)事兒整出來(lái)的一個(gè)閹割版的百度地圖,照著Shiny Gallery里面的某些大神那里得到的靈感,閑著沒(méi)事兒去里面轉(zhuǎn)轉(zhuǎn),確實(shí)可以學(xué)到很多東西。

Shiny

Shiny在這里就不過(guò)多介紹了,簡(jiǎn)言之他就是一個(gè)可以將R代碼的架構(gòu)轉(zhuǎn)換為HTML架構(gòu)的神奇的東西,換言之就是某尊大神將HTML給封裝成了R語(yǔ)言的一個(gè)包大概的工作原理是這樣的




一般網(wǎng)頁(yè)開發(fā)分為前段和后端,前端差不多就是網(wǎng)頁(yè)里的那些圖標(biāo)啊排版啊啥的,后端就是在你對(duì)網(wǎng)頁(yè)進(jìn)行操作時(shí),網(wǎng)頁(yè)該如何進(jìn)行反饋的交互邏輯。一般即使有HTML文件也是用不了的,因?yàn)闆](méi)有后端的話這網(wǎng)頁(yè)除了看沒(méi)什么用,不過(guò)牛逼的是Shiny還能幫你把后端給組織好。跟web開發(fā)類似,Shiny包里的架構(gòu)邏輯也是需要分好前端和后端的,分別用 ui.R和 server.R兩個(gè)文件來(lái)儲(chǔ)存。先來(lái)個(gè)簡(jiǎn)單的:

Sample 1

這是一個(gè)用來(lái)反映Kmeans均值聚類實(shí)時(shí)效果的簡(jiǎn)單應(yīng)用,可以自己DIY中心點(diǎn)個(gè)數(shù)以及要聚類的兩個(gè)變量,數(shù)據(jù)集是鳶尾花。
界面是這樣的,目前這圖里反應(yīng)的是將Sepal.Length和Sepal.Width分為3類后,樣本分布情況。




代碼也分為前端和后端,前端是ui,后端是sever

## The UI of the web library(shiny) library(ggplot2)ui <- shinyUI(fluidPage(headerPanel(title = 'Test Kmeans'),sidebarPanel(selectInput(inputId = 'Col',label = 'The Variables',choices = c('Sepal.Length','Sepal.Width','Petal.Length','Petal.Width'),selected = c('Sepal.Length','Sepal.Width'),multiple = T),numericInput(inputId = 'center',label = 'Centroids',value = 3,min = 1,max = 10,step = 1),submitButton(text='submit')),mainPanel(h1('The result of Kmeans'),plotOutput(outputId = 'plot')) ))## The server of the web server <- shinyServer(function(input,output){output$plot <- renderPlot({da <- iris[,input$Col]fit <- kmeans(da,centers = input$center)da$cluster <- fit$clusterda2 <- as.data.frame(fit$centers)ggplot()+geom_point(data = da,aes(x=da[,input$Col[1]],y=da[,input$Col[2]],color=factor(cluster)))+geom_point(data = da2,aes(x=da2[,names(da2)[1]],y=da2[,names(da2)[2]],color=factor(1:nrow(da2))),size=5,shape=3)+xlab(input$Col[1])+ylab(input$Col[2])}) })## Run the app shinyApp(ui = ui,server = server)

總結(jié)來(lái)說(shuō)就是ui里確定了在哪里input和output,server里通過(guò)input里的value來(lái)轉(zhuǎn)換為output,調(diào)用的原則是inputidoutputid,通過(guò)設(shè)定的id來(lái)一一對(duì)應(yīng),跟R6的面向?qū)ο缶幊桃粋€(gè)架構(gòu)方式。

地圖

完成這個(gè)app還有一個(gè)要素就是地圖。在各種涉及到“位置”的數(shù)據(jù)分析中,地圖在可視化中都扮演著一類非常重要的角色。有時(shí)候即使是一個(gè)很簡(jiǎn)單的分析,配上地圖可視化之后就會(huì)十分的高大上。雖然R語(yǔ)言中的ggplot2等包可以根據(jù)地圖邊界坐標(biāo)來(lái)畫出來(lái)地圖,但是都是靜態(tài)的地圖,所以我們使用的是R語(yǔ)言中一個(gè)公共地圖的接口leaflet。只需要幾行代碼就可以創(chuàng)建一個(gè)基礎(chǔ)的地圖層

library(leaflet) m <- leaflet() m%>%addTiles()

與ggplot2挺像的,先畫一個(gè)底,如果想diy的話,再自己往上加圖層,而且最重要的是地圖是動(dòng)態(tài)的而且可交互!比如說(shuō)下面這兩張圖。

如果我想將某個(gè)位置的坐標(biāo)給標(biāo)出來(lái)的話,就需要用額外的函數(shù)了

library(leaflet) m <- leaflet() m %>% addTiles() %>% ## 給某個(gè)經(jīng)度和緯度做標(biāo)記addPopus(lng=longtitude,lat=latitude)

坐標(biāo)數(shù)據(jù)

有了框架有了地圖,接下來(lái)還差坐標(biāo)數(shù)據(jù)了。對(duì)于個(gè)人來(lái)講,一個(gè)涵蓋全球各地坐標(biāo)的數(shù)據(jù)庫(kù)還是不現(xiàn)實(shí)的,所以就需要借用一些已有的成型的地圖數(shù)據(jù)庫(kù),比如說(shuō)百度地圖和谷歌地圖,可惜后者被墻了。這里再介紹一個(gè)R包,名字就叫作baidumap,可以通過(guò)調(diào)用百度地圖的API來(lái)獲取某個(gè)地址的經(jīng)緯度以及路線,輸出的結(jié)果是json格式(可選),所以這意味著我們還需要通過(guò)調(diào)用rjson包來(lái)解析json格式的文件。示例如下

library(baidumap) library(rjson)## 獲取“北京大學(xué)”的坐標(biāo) m <- getCoordinate(address='北京大學(xué)')

然后我們會(huì)獲得這樣格式的數(shù)據(jù)

{"status":0,"result":{"location":{"lng":116.31616663593383,"lat":39.997752940431137},"precise":0,"confidence":50,"level":"UNKNOWN"}}

通過(guò)函數(shù)fromJSON(m)格式就會(huì)變的更合理一點(diǎn),在R里面會(huì)以list形式表示。

$status [1] 0$result $result$location $result$location$lng [1] 116.3162$result$location$lat [1] 39.99775$result$precise [1] 0$result$confidence [1] 50$result$level [1] "UNKNOWN"

這是一個(gè)list格式數(shù)據(jù),我們可以直接用美元符號(hào)($)來(lái)調(diào)用里面的子元素,其中status表示反饋狀態(tài)(0表示成功,1表示找不到,2表示沒(méi)有輸入地點(diǎn)),lng和lat就不解釋了,level表示地點(diǎn)的等級(jí),不過(guò)只局限于“城市,區(qū)縣”這些比較宏觀的。

該包還有另外一個(gè)強(qiáng)大的函數(shù)是getRoute(origin,destination)可以獲得兩點(diǎn)之間的路線的坐標(biāo),配合上前面leaflet中的一個(gè)addPolyline()函數(shù),可以在地圖上標(biāo)注出路線圖。

整合

所有要素都配齊了,接下來(lái)的任務(wù)是將他們幾個(gè)整合在一起了,直接上代碼。

library(shiny) library(leaflet) library(baidumap) library(rjson)ui <- shinyUI(fluidPage(## the area for titleheaderPanel(title = 'Simulated BaiduMap'), ## plot the leaflet in the whole pageleafletOutput(outputId = 'map',width = '1920px',height = '1080px'),## control inputs panel and buttonabsolutePanel(width = 430,top=200,left = 'auto',draggable = T,textInput(inputId = 'Loc',label = 'THE PLACE'),textInput(inputId = 'Start',label = 'FROM',width = "50%"),textInput(inputId = 'End',label = 'TO',width = "50%"),selectInput(inputId = 'selected',label = 'Route or Loc',choices = c('Loc','Route'),selected = 'Loc',multiple = F),textOutput(outputId = 'Request'),submitButton(text = "Submit")) ))server <- shinyServer(function(input, output) {## acquire the coordinate from rjson filegetcoord <- function(x){## x is a name of some placex <- fromJSON(getCoordinate(x))return(x)}## output leaflet map to the id:mapoutput$map <- renderLeaflet({m <- leaflet()m <- m%>%addTiles()if(input$selected == 'Loc'){temp <- getcoord(input$Loc)if(temp$status!=0){output$Request <- renderText({c('The location failed to be found')})m}else{output$Request <- renderText({c('The location is found successfully')})m %>% addMarkers(lng=temp$result$location$lng,lat=temp$result$location$lat,popup = paste0(input$Loc,'--',temp$result$level))}}else{temp1 <- getcoord(input$Start)temp2 <- getcoord(input$End)if(temp1$status==0&temp2$status==0){output$Request <- renderText({c('Both start point and end point are valid')})route <- getRoute(input$Start,input$End)m%>%addPolylines(route$lon,route$lat)%>%addMarkers(lng=route$lon[c(1,nrow(route))],lat=route$lat[c(1,nrow(route))],popup = c(paste0(input$Start,'--',temp1$result$level),paste0(input$End,'--',temp2$result$level)))}else{output$Request <- renderText({c('One or both of origin and destination is invalid')})}}}) })

就不解釋代碼了,主要兩種功能

  • 輸出定點(diǎn)坐標(biāo):將Route or Loc設(shè)為L(zhǎng)oc,然后在THE PLACE里輸入目標(biāo)地點(diǎn),然后submit就OK
  • 輸出兩點(diǎn)路線:將Route or Loc設(shè)為Route,然后分別在FROM和TO里輸入起始點(diǎn)和終點(diǎn),然后submit
  • 效果還是蠻好的,比如說(shuō)我想找天安門到清華大學(xué)的路線:

    總結(jié)

    博客原文還是發(fā)在了個(gè)人網(wǎng)頁(yè)上Zhuifengmu,如果感興趣的話可以嘗試下我之前發(fā)布的一個(gè)粗糙版本的ChinaMap,由于是國(guó)外的網(wǎng)不一定登的上去。文章是水出來(lái)的并沒(méi)有注重細(xì)節(jié),歡迎指正。

    總結(jié)

    以上是生活随笔為你收集整理的【Shiny】基于R-Shiny制作地图App(百度地图)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。