在R传单中包含风数据的交互式动态地图?


11

我有一些这样的数据:

     longitude  latitude          speed        direction
1    6.10722222 46.23639           4           360
2    6.95416667 43.54694           4           360
3    7.21472222 43.66556          13           330
4    4.01666667 48.32167           7           290
5    2.30833333 43.21611          14           290
6    2.48305556 44.40806          13           320
7    5.21500000 43.43694          19           330
8    4.92361111 43.52278          32           320
9    5.10805556 43.60306          26           330
10  -0.44972222 49.17389           6           290
11   0.16000000 49.36389           3             0
12   2.41666667 44.89750           5           290
13  -0.31361111 45.65583           8           310
14   0.21888889 45.72972           7            70
15  -1.19527778 46.17917          10           330
16   2.64250000 47.05722           4           270
17   1.48555556 45.03972           8           320
18   8.80250000 41.92417           5            60
19   9.09638889 41.50306           2             0
20   9.40527778 41.92667          15           350
21   9.48472222 42.55083          13            10
22   8.79277778 42.52056           9            50
23   5.09083333 47.26639           9           330
24  -3.47444444 48.75556           6           330
25  -2.85666667 48.53778           6           330
26   0.52055556 44.82444           4           280
27   4.96833333 44.91611          22           360
28   1.20666667 49.01833           6           280
29   1.37944444 48.05806           5           330
30  -3.81666667 48.60111           9           330
31  -4.42194444 48.44778          10           330
32  -4.16805556 47.97556          12           340
33  -4.15166667 48.53028          10           340
34  -4.44583333 48.28194          12           330
35   4.41611111 43.75778          14           360
36   1.36777778 43.63500          14           310
37  -0.71527778 44.82861           4           290
38  -1.13138889 44.53528           2           360
39   3.96111111 43.58333           5            30
40   3.35333333 43.32333          20           320
41  -2.08000000 48.58833          12           340
42  -1.73222222 48.07194           4           310
43   1.72250000 46.85889           3           310
44   0.72333333 47.43306           3           300
45   5.33222222 45.36333          13           360
46   5.42444444 47.04222           8           340
47  -1.06888889 43.68917           4           310
48  -0.50916667 43.91167           6           300
49   1.68916667 47.31750           0             0
50   4.29722222 45.53389           8           340
51  -1.60805556 47.15778           4           330
52  -2.15666667 47.31056           8           300
53   1.75944444 47.98944           4           320
54   0.59055556 44.17500           8           290
55  -0.31194444 47.56028           3            60
56  -1.47527778 49.65083           8           340
57   4.15666667 49.20861           3             0
58   4.20611111 48.77333           4           320
59   4.90805556 48.63389           4            30
60  -0.74277778 48.03222           3           330
61   6.22583333 48.69278           5           340
62   5.95500000 48.58389           4           310
63  -3.43944444 47.76083           4           250
64  -2.72805556 47.72194           4           310
65   6.24638889 48.97861           6           320
66   3.11083333 47.00417           3           280
67   3.08638889 50.56417           6           280
68   2.11277778 49.45500           4           310
69   2.51916667 49.25333           0             0
70   1.62750000 50.51472           5           330
71   3.16222222 45.78639           5           350
72  -1.53138889 43.46889          16           330
73  -0.41833333 43.38083           7           350
74   0.00000000 43.18694           7           340
75   2.86972222 42.74083          15           330
76   7.63416667 48.54222           7           320
77   7.52916667 47.59028           1             0
78   7.35916667 48.11028           3             0
79   5.08111111 45.72556          10           350
80   4.93861111 45.73028          10           350
81   6.35972222 47.78806           3             0
82   4.02111111 46.40639           8           310
83   0.20166667 47.94917           1             0
84   5.88166667 45.63806           2             0
85   6.09888889 45.92944           8           360
86   1.18388889 49.39222           5           290
87   0.08805556 49.53417           7            10
88   2.67027778 48.60667           3           300
89   2.11111111 48.74972           4           310
90   2.19166667 48.77417           4           360
91   2.69222222 49.97111           4           360
92   2.28916667 43.55694          13           330
93   6.14583333 43.09722           7           290
94   4.90194444 43.90694          14           290
95   4.85972222 44.14833          13           320
96  -1.38166667 46.70250          19           330
97   0.30666667 46.58750          32           320
98   1.18027778 45.86111          26           330
99   6.06666667 48.32528           6           290
100  2.43222222 48.94972           3             0
101  2.35944444 48.72556           5           290
102  2.54861111 49.01000           8           310
103  2.04083333 49.09667           7            70

我想在R leaflet包中显示风速数据(速度和方向),但是到目前为止还没有找到很多例子。

这次讨论非常有趣:简化R中不规则间隔的风数据的流线,但是如何在带有小叶的交互式地图上显示结果呢?

我想要这样的东西:http : //apps.socib.es/Leaflet.TimeDimension/examples/example3.html


2
几个月前,我也在寻找类似的东西。我最终使用了polylines(),而不是箭头,而是在线条的末尾添加了点以指示风向。您还可以创建图标(指示风向的箭头),并将addMarkers()与个性化图标一起使用。但是希望其他人会给出答案:-)
MLavoie '16

我可以创建真实的标记,但是如何在风向中定义标记的方向呢?
zina_GIS '16

1
不幸的是,这是手动工作(您可以创建8个不同的标记(S,SE,SW等)),但是标记可能不是最准确的解决方案……
MLavoie 2016年

1
必须使用R吗?还是可以使用GeoServer生成WMS图层以在Leaflet中显示(在R中?)?geoserver.geo-solutions.it/multidim/en/accessing_multidim/rtx/...
伊恩·特顿

1
@iant想要这个:apps.socib.es/Leaflet.TimeDimension/examples/example3.html有什么建议吗?我使用R中的传单
zina_GIS

Answers:


9

我错过了数据集中的一些信息,例如CRS和时间戳;因此我创建了自己的数据集以提供可重复的示例。

这是创建交互式风向图的一种建议:一种是时间静态的,另一种是动态的:

  1. 准备df包含地理参考数据的数据框():风速和风向。
  2. df与辅助坐标互补,用于将风表示为箭头线。
  3. 创建SpatialLinesDataFrame要在中使用的类的对象leaflet
  4. 生成风速和风向的交互式和静态地图。
  5. 生成风速和风向的交互式动态地图(与R包集成shiny)。

请参见下面的注释代码和输出:

#------------------------------
#Step 1 - Prepare data frame (`df`) with georeferenced data: wind speed and wind direction.

#Sample data (n=12; data collected in 4 different days of December, 2016)

#Projected coordinates. CRS = EPSG3857 (http://spatialreference.org/ref/sr-org/7483/)
#Starting x and y coordinates (where wind data was observed).
start.x <- c(-5320000,-5316500,-5316020,-5316800,-5316050,-5320400,-5321800,-5320080,-5325000,-5320010,-5322165,-5320786) #longitude
start.y <- c(-2180000,-2185900,-2185300,-2184000,-2180700,-2180010,-2189000,-2187500,-2183030,-2184600,-2185025,-2182384) #latitute

#Wind variables (speed, direction and date)
w.speed <- c(10,75,93,40,23,8,65,45,29,54,35,28) #wind speed (km/h)
w.direction <- c(330,80,35,240,170,90,180,20,231,360,290,55) #wind azimuth angle (degrees)
w.date <- do.call("as.Date",
                 list(x = c("1-Dec-2016", "1-Dec-2016", "1-Dec-2016", "5-Dec-2016", "5-Dec-2016", "5-Dec-2016", "9-Dec-2016", "9-Dec-2016", "9-Dec-2016", "12-Dec-2016", "12-Dec-2016", "12-Dec-2016"),
                      format = "%d-%b-%Y")) #date of data collection (yyyy-mm-dd)
id <- c(1:length(start.x)) #id of sample data

#Dataframe with georeferenced wind data
df <- data.frame(id=id,start.x=start.x,start.y=start.y,w.speed=w.speed,w.direction=w.direction,w.date=w.date)
head(df,5)

#------------------------------
#Step 2 - Complement `df` with auxiliary coordinates for representing wind as arrowhead lines.

#Line parameters
line.length <- 1000 #length of polylines representing wind in the map (meters)
arrow.length <- 300 #lenght of arrowhead leg (meters)
arrow.angle <- 120 #angle of arrowhead leg (degrees azimuth)

#Generate data frame with auxiliary coordinates
end.xy.df <- data.frame(end.x=NA,end.y=NA,end.arrow.x=NA,end.arrow.y=NA)

for (i in c(1:nrow(df))){

#coordinates of end points for wind lines (the initial points are the ones where data was observed)
if (df$w.direction[i] <= 90) {
    end.x <- df$start.x[i] + (cos((90 - df$w.direction[i]) * 0.0174532925) * line.length)
} else if (df$w.direction[i] > 90 & df$w.direction[i] <= 180) {
    end.x <- df$start.x[i] + (cos((df$w.direction[i] - 90) * 0.0174532925) * line.length)
} else if (df$w.direction[i] > 180 & df$w.direction[i] <= 270) {
  end.x <- df$start.x[i] - (cos((270 - df$w.direction[i]) * 0.0174532925) * line.length)
} else {end.x <- df$start.x[i] - (cos((df$w.direction[i] - 270) * 0.0174532925) * line.length)}

if (df$w.direction[i] <= 90) {
    end.y <- df$start.y[i] + (sin((90 - df$w.direction[i]) * 0.0174532925) * line.length)
} else if (df$w.direction[i] > 90 & df$w.direction[i] <= 180) {
    end.y <- df$start.y[i] - (sin((df$w.direction[i] - 90) * 0.0174532925) * line.length)
} else if (df$w.direction[i] > 180 & df$w.direction[i] <= 270) {
    end.y <- df$start.y[i] - (sin((270 - df$w.direction[i]) * 0.0174532925) * line.length)
} else {end.y <- df$start.y[i] + (sin((df$w.direction[i] - 270) * 0.0174532925) * line.length)}

#coordinates of end points for arrowhead leg lines (the initial points are the previous end points)
end.arrow.x <- end.x + (cos((df$w.direction[i] + arrow.angle) * 0.0174532925) * arrow.length)
end.arrow.y <- end.y - (sin((df$w.direction[i] + arrow.angle) * 0.0174532925) * arrow.length)

end.xy.df <- rbind(end.xy.df,c(end.x,end.y,end.arrow.x,end.arrow.y)) 
}

end.xy <- end.xy.df[-1,]
df <- data.frame(df,end.xy) #df with observed and auxiliary variables
head(df,3)

#------------------------------
#Step 3 - Create an object of class `SpatialLinesDataFrame` to use within `leaflet`.

lines <- data.frame(cbind(lng=c(df$start.x,df$end.x,df$end.arrow.x),
                          lat=c(df$start.y,df$end.y,df$end.arrow.y),
                          id=c(rep(df$id,3))))

lines.list <- list()

library(sp)

for (i in c(1:max(lines$id))){
line <- subset(lines,lines$id==i)
line <- as.matrix(line[,c(1:2)])
line <- Line(line) #object of class 'Line'
lines.list[[i]] <- Lines(list(line), ID = i) #list of 'objects'Lines' 
}

sp.lines <- SpatialLines(lines.list) #object of class 'SpatialLines'
proj4string(sp.lines) <- CRS("+init=epsg:3857") #define CRS

#Convert CRS to geographic coordinates (http://spatialreference.org/ref/epsg/4326/)
#for overlaying on OpenStreetMaps tiles in Leaflet
sp.lines <- spTransform(sp.lines, CRS("+init=epsg:4326"))

rownames(df) = df$id
#Join wind variables (id, speed, direction and date) to object of class 'SpatialLines'
sp.lines.df <- SpatialLinesDataFrame(sp.lines, df[,c(1,4:6)]) #object of class 'SpatialLinesDataFrame'
str(sp.lines.df) #inspect object structure

#------------------------------
# Code for next steps mostly adapted from https://rstudio.github.io/leaflet/
#------------------------------

#------------------------------
#Step 4 - Generate interactive and **static** map of wind speed and direction.

library(leaflet)

#popup settings
labels <- paste0("ID: ",sp.lines.df@data$id,
                 "<br>Wind speed: ",sp.lines.df@data$w.speed," Km/h<br>",
                 "Wind direction: ",sp.lines.df@data$w.direction," degrees azimuth<br>",
                 "Date: ", sp.lines.df@data$w.date)

#pallete settings
pal <- colorNumeric(palette = colorRampPalette(c("red", "blue"))(5),
                    domain = 0:max(sp.lines.df@data$w.speed))

#Create object fo class 'leaflet' 'htmlwidget'
m <- leaflet(sp.lines.df) %>%
  addTiles() %>%  # add default OpenStreetMap map tiles
  addPolylines(color = ~pal(w.speed), opacity=1, weigh = 3, popup = labels) %>%
  addLegend("bottomright", pal = pal, values = ~w.speed,
          title = "Wind speed <br> (km/h)",
          opacity = 1) %>%
  fitBounds(sp.lines.df@bbox[1,1], sp.lines.df@bbox[2,1], sp.lines.df@bbox[1,2], sp.lines.df@bbox[2,2])

#Plot map
m

在此处输入图片说明

#------------------------------
#Step 5 - Generate interactive and **dynamic** map of wind speed and direction.

library(shiny)

#User interface (UI) settings
ui <- fluidPage(leafletOutput("m.dynamic"),
                absolutePanel(top = 10,
                              right = 10,
                              draggable = TRUE,
                              sliderInput("range",
                                          "Time of data collection:",
                                          min = min(sp.lines.df@data$w.date),
                                          max = max(sp.lines.df@data$w.date),
                                          value = min(sp.lines.df@data$w.date),
                                          step = 4,
                                          animate=TRUE)))

#Name @coords slot of SpatialLinesDataFrame: 'lng' and 'lat'
#task necessary for 'observer' within 'server' function
for (i in c(1:max(sp.lines.df@data$id))) {
  colnames(sp.lines.df@lines[[i]]@Lines[[1]]@coords) <- c("lng","lat")
}

#Server logic
server <- function(input, output){
  filteredData <- reactive({
    sp.lines.df[sp.lines.df@data$w.date == input$range[1],]
  })
  output$m.dynamic <- renderLeaflet({
    leaflet(sp.lines.df) %>%
      addTiles() %>%  # Add default OpenStreetMap map tiles
      addLegend("bottomright",pal = pal, values = ~w.speed, title = "Wind speed <br> (km/h)", opacity = 0.9) %>%
      fitBounds(sp.lines.df@bbox[1,1], sp.lines.df@bbox[2,1], sp.lines.df@bbox[1,2], sp.lines.df@bbox[2,2])
  })
  observe({
    leafletProxy("m.dynamic", data = filteredData()) %>%
      clearShapes() %>%
      addPolylines(color = ~pal(w.speed), opacity=1, weigh = 3, popup = labels)
  })
}

# Complete app with UI and server components
shinyApp(ui, server)

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.