Related
I want to convert my dataframe from wide to long but based on the character vector in one column (based on residents number from the following dput.)
From the following dput, the outcome should have a total of three rows showing all the 3 residents. Is there a way to do it? I tried using seperate rows but the output is not what I desire.
Tried using
Building_Details_Trial_50 %>% tidyr::separate_rows(residents)
dput
structure(list(time = "Mar 22", buildingId = "50", region = "Central",
geometry = structure(list(structure(list(structure(c(-447.361154068258,
-447.557850744738, -533.811390293442, -536.961556093902,
-443.736917153567, -447.361154068258, 5919.51770006977, 5906.87385860642,
5908.2156806004, 5958.8966109417, 5959.54382538916, 5919.51770006977
), dim = c(6L, 2L))), class = c("XY", "POLYGON", "sfg"))), class = c("sfc_POLYGON",
"sfc"), precision = 0, bbox = structure(c(xmin = -536.961556093902,
ymin = 5906.87385860642, xmax = -443.736917153567, ymax = 5959.54382538916
), class = "bbox"), crs = structure(list(input = NA_character_,
wkt = NA_character_), class = "crs"), n_empty = 0L),
count = 3L, geom_points = structure(list(structure(c(-490.403818453599,
5933.7360887923), class = c("XY", "POINT", "sfg"))), class = c("sfc_POINT",
"sfc"), precision = 0, bbox = structure(c(xmin = -490.403818453599,
ymin = 5933.7360887923, xmax = -490.403818453599, ymax = 5933.7360887923
), class = "bbox"), crs = structure(list(input = NA_character_,
wkt = NA_character_), class = "crs"), n_empty = 0L),
long = -490.403818453599, lat = 5933.7360887923, residents = list(
c("556", "155", "143"))), row.names = 1L, sf_column = "geometry", agr = structure(c(time = NA_integer_,
buildingId = NA_integer_, region = NA_integer_, count = NA_integer_,
long = NA_integer_, lat = NA_integer_, residents = NA_integer_
), levels = c("constant", "aggregate", "identity"), class = "factor"), class = c("sf",
"tbl_df", "tbl", "data.frame"))
Ideal output
Residents
buildingId
Region
556
50
Central
155
50
Central
143
50
Central
I'm attempting to pro-grammatically add multiple vertical polylines of specific length to contiguous polygons in R. The number and length of the polylines should be specified by the user and can range from 1 to 8 polylines and 5000 to 10000 feet long per contiguous polygons. How can I achieve this in R?
I'm able to do this manually by the use of the mapedit package for a couple of polygons but I would like to automate the process for several thousand contiguous polygons.
# Load required libraries
library(mapedit)
library(mapview)
library(dplyr)
library(sp)
# Sample polygons and polylines
geometry = structure(list(structure(list(structure(c(8.769563, 8.769563,
8.770507, 8.770507, 8.769563, 50.815273, 50.815714, 50.815714,
50.815273, 50.815273), .Dim = c(5L, 2L))), class = c("XY", "POLYGON",
"sfg")), structure(list(structure(c(8.769568, 8.769568, 8.770507,
8.770507, 8.769568, 50.814852, 50.81527, 50.81527, 50.814852,
50.814852), .Dim = c(5L, 2L))), class = c("XY", "POLYGON", "sfg"
)), structure(list(structure(c(8.769568, 8.769568, 8.770502,
8.770502, 8.769568, 50.814412, 50.814849, 50.814849, 50.814412,
50.814412), .Dim = c(5L, 2L))), class = c("XY", "POLYGON", "sfg"
)), structure(list(structure(c(8.769568, 8.769568, 8.770502,
8.770502, 8.769568, 50.814005, 50.814408, 50.814408, 50.814005,
50.814005), .Dim = c(5L, 2L))), class = c("XY", "POLYGON", "sfg"
)), structure(list(structure(c(8.770502, 8.770502, 8.771301,
8.771301, 8.770502, 50.815273, 50.815717, 50.815717, 50.815273,
50.815273), .Dim = c(5L, 2L))), class = c("XY", "POLYGON", "sfg"
)), structure(list(structure(c(8.770518, 8.770518, 8.771301,
8.771301, 8.770518, 50.814852, 50.81527, 50.81527, 50.814852,
50.814852), .Dim = c(5L, 2L))), class = c("XY", "POLYGON", "sfg"
)), structure(list(structure(c(8.770507, 8.770507, 8.771301,
8.771301, 8.770507, 50.814408, 50.814849, 50.814849, 50.814408,
50.814408), .Dim = c(5L, 2L))), class = c("XY", "POLYGON", "sfg"
)), structure(list(structure(c(8.770507, 8.770507, 8.771296,
8.771296, 8.770507, 50.814005, 50.814405, 50.814405, 50.814005,
50.814005), .Dim = c(5L, 2L))), class = c("XY", "POLYGON", "sfg"
)), structure(c(8.769794, 8.769783, 50.814785, 50.814076), .Dim = c(2L,
2L), class = c("XY", "LINESTRING", "sfg")), structure(c(8.770051,
8.770035, 50.814785, 50.814069), .Dim = c(2L, 2L), class = c("XY",
"LINESTRING", "sfg")), structure(c(8.770271, 8.77026, 50.814781,
50.814076), .Dim = c(2L, 2L), class = c("XY", "LINESTRING", "sfg"
))), class = c("sfc_GEOMETRY", "sfc"), precision = 0, bbox = structure(c(xmin = 8.769563,
ymin = 50.814005, xmax = 8.771301, ymax = 50.815717), class = "bbox"), crs = structure(list(
epsg = 4326L, proj4string = "+proj=longlat +datum=WGS84 +no_defs"), class = "crs"), classes = c("POLYGON",
"POLYGON", "POLYGON", "POLYGON", "POLYGON", "POLYGON", "POLYGON",
"POLYGON", "LINESTRING", "LINESTRING", "LINESTRING"), n_empty = 0L)
# Visualize geometry
mapview(geometry)
I attempted to create regularly sampled points via the spsample function inside the polygons and connecting them by lines but was unsuccessful. appreciate any help I can get.
Here's one way to create lines given a polygon. It's probably not exactly what you want, since your request is quite specific, but hopefully the code is generic enough that you cn adapt it.
library(sf)
library(purrr)
polygon <- st_polygon(list(matrix(c(1,1,2,2,1,1,0,0,1,1), ncol = 2)))
# use polygon bounding box to o compute line parameters
bb <- st_bbox(polygon)
number_of_lines <- 5
line_length <- (bb[["ymax"]] - bb[["ymin"]]) / 1.2
y_offset <- bb[["ymin"]] + (bb[["ymax"]] - bb[["ymin"]] - line_length) / 2
# compute coordinates
xs <- seq(bb[["xmin"]], bb[["xmax"]], length.out = number_of_lines)
ys <- bb[["ymin"]] + line_length
# create a linestring
lines <- purrr::map2(xs, ys, ~st_linestring(matrix(c(.x, .x, .y,y_offset), ncol = 2))) %>% st_sfc(crs = st_crs(polygon))
# view
plot(polygon)
plot(lines, col = 2, add = TRUE)
I have the following map of Mexico. It shows all of its municipalities and around 400 weather stations.
I want to create a 10km buffer around each station and eventually, associate each municipality to a station that is located within each radius.
The map and the stations are stored on separate sf objects. I tired the following:
buffers <- st_buffer(stations, dist = 1)
I thought the dist argument was set to kilometers, so I tried dist = 10. Unfortunately, this returned HUGE buffers for each station. That's why I am using dist = 1, but even these buffers are as big as a state! This question, suggests I transform my stations to Irish Grid, but I couldn't replicate the accepted answer. I am now wondering what unit the dist argument is set to.
From the aforementioned question, I assume it's set to degrees. How can I set a 10km buffer around each station?
Additional info:
My CRS is set to 4326 on both objects (the Mexican map and the stations).
This is my stations data:
> dput(head(stations))
structure(list(station_number = c(1004L, 1005L, 1008L, 1012L,
1017L, 1018L), station_alt = c(1925, 1844, 2323, 1589, 2172,
2053), month = c(9L, 9L, 9L, 9L, 9L, 9L), Mean_min = c(11.6,
12.75, 12.25, 13.9666666666667, 12.9, 12.6833333333333), Mean_max = c(26.9333333333333,
26.85, 24.0833333333333, 29.0333333333333, 24.8666666666667,
26.1333333333333), months_observed = c(5L, 5L, 5L, 5L, 5L, 5L
), geometry = structure(list(structure(c(-102.199, 22.001), class = c("XY",
"POINT", "sfg")), structure(c(-102.372, 21.781), class = c("XY",
"POINT", "sfg")), structure(c(-102.135, 22.203), class = c("XY",
"POINT", "sfg")), structure(c(-102.802, 21.794), class = c("XY",
"POINT", "sfg")), structure(c(-102.444, 22.233), class = c("XY",
"POINT", "sfg")), structure(c(-102.415, 22.141), class = c("XY",
"POINT", "sfg"))), class = c("sfc_POINT", "sfc"), precision = 0, bbox = structure(c(xmin = -102.802,
ymin = 21.781, xmax = -102.135, ymax = 22.233), class = "bbox"), crs = structure(list(
epsg = NA_integer_, proj4string = NA_character_), class = "crs"), n_empty = 0L)), sf_column = "geometry", agr = structure(c(station_number = NA_integer_,
station_alt = NA_integer_, month = NA_integer_, Mean_min = NA_integer_,
Mean_max = NA_integer_, months_observed = NA_integer_), .Label = c("constant",
"aggregate", "identity"), class = "factor"), row.names = c(NA,
6L), class = c("sf", "data.frame"))
Your coordinates are long/lat, so the distance will be in degrees. You should first project to a spatial reference in meter units and then take 10 000 meters.
The manual of st_buffer says this about the dist argument:
in case dist is a units object, it should be convertible to
arc_degree if x has geographic coordinates, and to st_crs(x)$units
otherwise
If you leave the coordinates in 4326 you should be able to take something like 0.1 which should be about 11 km for Mexico, but you will see a warning message:
In st_buffer.sfc(st_geometry(x), dist, nQuadSegs, endCapStyle =
endCapStyle, : st_buffer does not correctly buffer
longitude/latitude data
So first convert to another projection (in meter) and enter the distance in meters. This should work, which uses EPSG 7801:
library(sf)
pois <- st_as_sf(stations)
st_crs(pois) <- 4326
pois <- st_transform(pois, crs = 7801)
plot(st_geometry(pois))
buff <- st_buffer(pois, dist = 10000)
plot(st_geometry(buff), add = TRUE)
Control with leaflet and the measure tool:
buff <- st_transform(buff, crs = 4326)
library(leaflet)
leaflet() %>%
addTiles() %>%
addMeasure(primaryLengthUnit = "meters") %>%
addMarkers(data = pois) %>%
addPolygons(data = buff)
I am trying to provide extra information in a table below a plotly map using event_data.
I found this: https://community.plot.ly/t/how-to-return-the-same-event-data-information-for-selected-points-even-after-modifying-the-data/5847. A good example using ggplot by adding the key column to the aes:
ggplot(mtcars, aes(mpg, wt, col = I(col), key = key))
But how can I add a key column to a scattergl plotly map in order for the key popping up in the event_data? Any help would be greatly appreciated.
R Shiny code:
library(plotly)
library(shiny)
ui <- fluidPage(
plotlyOutput("plot"),
verbatimTextOutput("event")
)
server <- function(input, output, session) {
#df sample using dput
df <- structure(list(col_group = structure(1:8, .Label = c("1", "2",
"3", "4", "5", "6", "7", "8"), class = "factor"), color = structure(c(4L,
6L, 7L, 8L, 5L, 3L, 2L, 1L), .Label = c("#1A9850", "#66BD63",
"#A6D96A", "#D73027", "#D9EF8B", "#F46D43", "#FDAE61", "#FEE08B"
), class = "factor"), geometry = structure(list(structure(c(4.52343199617246,
4.52324233358547, 4.52267342343957, 4.52224662532908, 4.52210428346744,
4.52200925015845, 4.52192088448668, 4.52180475361204, 4.52172945325391,
4.52168196905882, 4.5215535740952, 4.52095980475523, 4.52076420632298,
4.52062274547478, 51.9453195440486, 51.9453722803981, 51.945526317454,
51.9456480852256, 51.9456928353329, 51.9457296098645, 51.9457705951341,
51.9458530114811, 51.945914910501, 51.9459312169901, 51.9459510896027,
51.9459966849614, 51.9460077291392, 51.9460066867221), .Dim = c(14L,
2L), class = c("XY", "LINESTRING", "sfg")), structure(c(4.4964540696277,
4.49696710232736, 51.9086692611627, 51.9084484303039), .Dim = c(2L,
2L), class = c("XY", "LINESTRING", "sfg")), structure(c(4.13635479859532,
4.13644010080625, 51.975098751212, 51.9751715711302), .Dim = c(2L,
2L), class = c("XY", "LINESTRING", "sfg")), structure(c(4.47801457239531,
4.47834576882542, 51.9300740588744, 51.9304218318716), .Dim = c(2L,
2L), class = c("XY", "LINESTRING", "sfg")), structure(c(4.45974369011875,
4.46029492493512, 4.46033964902157, 51.9290774018138, 51.9284345596986,
51.9283809798498), .Dim = 3:2, class = c("XY", "LINESTRING",
"sfg")), structure(c(4.43886518844695, 4.43891013390463, 4.43910559159559,
4.43913561800293, 51.93455577157, 51.9344932127658, 51.9341891712133,
51.9341444695365), .Dim = c(4L, 2L), class = c("XY", "LINESTRING",
"sfg")), structure(c(4.54844667292407, 4.55002805772657, 51.9658870347267,
51.9661409927825), .Dim = c(2L, 2L), class = c("XY", "LINESTRING",
"sfg")), structure(c(4.47522875290306, 4.47598748813623, 51.9347985281278,
51.9353886781931), .Dim = c(2L, 2L), class = c("XY", "LINESTRING",
"sfg"))), class = c("sfc_LINESTRING", "sfc"), precision = 0, bbox = structure(c(xmin = 4.13635479859532,
ymin = 51.9084484303039, xmax = 4.55002805772657, ymax = 51.9751715711302
), class = "bbox"), crs = structure(list(epsg = 4326L, proj4string = "+proj=longlat +datum=WGS84 +no_defs"), class = "crs"), n_empty = 0L),
key = c("1", "8000", "10000", "12000", "14000", "16000",
"18000", "22000")), row.names = c(1L, 8000L, 10000L, 12000L,
14000L, 16000L, 18000L, 22000L), class = c("sf", "data.frame"
), sf_column = "geometry", agr = structure(c(col_group = NA_integer_,
color = NA_integer_, key = NA_integer_), .Label = c("constant",
"aggregate", "identity"), class = "factor"))
#plotly
output$plot <- renderPlotly({
plot_geo(df, type = "scattergl", mode = "lines",
color = ~col_group, colors = rev(RColorBrewer::brewer.pal(8, name = "RdYlGn"))
)
})
#event_data
output$event <- renderPrint({
d <- event_data("plotly_click")
if (is.null(d)) "Click events appear here (double-click to clear)" else {
df_select <- df %>% tibble::rownames_to_column() %>% filter(col_group==d$curveNumber-7) %>% filter(row_number()==d$pointNumber+1)
browser()
print(df_select)
}
})
}
shinyApp(ui, server)
Solved using customdata and updated plotly package. Perhaps of use for someone else:
library(plotly)
library(shiny)
ui <- fluidPage(
plotlyOutput("plot"),
verbatimTextOutput("event")
)
server <- function(input, output, session) {
#df sample using dput
df <- structure(list(col_group = structure(1:8, .Label = c("1", "2",
"3", "4", "5", "6", "7", "8"), class = "factor"), color = structure(c(4L,
6L, 7L, 8L, 5L, 3L, 2L, 1L), .Label = c("#1A9850", "#66BD63",
"#A6D96A", "#D73027", "#D9EF8B", "#F46D43", "#FDAE61", "#FEE08B"
), class = "factor"), geometry = structure(list(structure(c(4.52343199617246,
4.52324233358547, 4.52267342343957, 4.52224662532908, 4.52210428346744,
4.52200925015845, 4.52192088448668, 4.52180475361204, 4.52172945325391,
4.52168196905882, 4.5215535740952, 4.52095980475523, 4.52076420632298,
4.52062274547478, 51.9453195440486, 51.9453722803981, 51.945526317454,
51.9456480852256, 51.9456928353329, 51.9457296098645, 51.9457705951341,
51.9458530114811, 51.945914910501, 51.9459312169901, 51.9459510896027,
51.9459966849614, 51.9460077291392, 51.9460066867221), .Dim = c(14L,
2L), class = c("XY", "LINESTRING", "sfg")), structure(c(4.4964540696277,
4.49696710232736, 51.9086692611627, 51.9084484303039), .Dim = c(2L,
2L), class = c("XY", "LINESTRING", "sfg")), structure(c(4.13635479859532,
4.13644010080625, 51.975098751212, 51.9751715711302), .Dim = c(2L,
2L), class = c("XY", "LINESTRING", "sfg")), structure(c(4.47801457239531,
4.47834576882542, 51.9300740588744, 51.9304218318716), .Dim = c(2L,
2L), class = c("XY", "LINESTRING", "sfg")), structure(c(4.45974369011875,
4.46029492493512, 4.46033964902157, 51.9290774018138, 51.9284345596986,
51.9283809798498), .Dim = 3:2, class = c("XY", "LINESTRING",
"sfg")), structure(c(4.43886518844695, 4.43891013390463, 4.43910559159559,
4.43913561800293, 51.93455577157, 51.9344932127658, 51.9341891712133,
51.9341444695365), .Dim = c(4L, 2L), class = c("XY", "LINESTRING",
"sfg")), structure(c(4.54844667292407, 4.55002805772657, 51.9658870347267,
51.9661409927825), .Dim = c(2L, 2L), class = c("XY", "LINESTRING",
"sfg")), structure(c(4.47522875290306, 4.47598748813623, 51.9347985281278,
51.9353886781931), .Dim = c(2L, 2L), class = c("XY", "LINESTRING",
"sfg"))), class = c("sfc_LINESTRING", "sfc"), precision = 0, bbox = structure(c(xmin = 4.13635479859532,
ymin = 51.9084484303039, xmax = 4.55002805772657, ymax = 51.9751715711302
), class = "bbox"), crs = structure(list(epsg = 4326L, proj4string = "+proj=longlat +datum=WGS84 +no_defs"), class = "crs"), n_empty = 0L),
key = c("1", "8000", "10000", "12000", "14000", "16000",
"18000", "22000")), row.names = c(1L, 8000L, 10000L, 12000L,
14000L, 16000L, 18000L, 22000L), class = c("sf", "data.frame"
), sf_column = "geometry", agr = structure(c(col_group = NA_integer_,
color = NA_integer_, key = NA_integer_), .Label = c("constant",
"aggregate", "identity"), class = "factor"))
#plotly
output$plot <- renderPlotly({
plot_geo(df, type = "scattergl", mode = "lines",
customdata = ~key,
color = ~col_group, colors = rev(RColorBrewer::brewer.pal(8, name = "RdYlGn"))
)
})
#event_data
output$event <- renderPrint({
d <- event_data("plotly_click")
if (is.null(d)) "Click events appear here (double-click to clear)" else {
df_select <- df[df$key %in% d$customdata,]
print(df_select)
}
})
}
shinyApp(ui, server)
I have a region with sub regions. For each sub region I have a simple ggplot, that I want to put into the center of each region.
I am using a leaflet package, so my code looks like this:
employees_spdf <- structure(list(ID = structure(c(7L, 8L, 4L, 3L, 10L, 1L, 9L,
6L, 2L, 5L), .Label = c("75006", "78280", "91370", "92110", "92420",
"93270", "93440", "95000", "95330", "95400"), class = "factor"),
n = c(10L, 79L, 99L, 16L, 55L, 94L, 25L, 40L, 51L, 44L),
geometry = structure(list(structure(c(2.423864, 48.95034085
), class = c("XY", "POINT", "sfg")), structure(c(2.05650642,
49.0277569), class = c("XY", "POINT", "sfg")), structure(c(2.30575224,
48.90353573), class = c("XY", "POINT", "sfg")), structure(c(2.25171264,
48.75044317), class = c("XY", "POINT", "sfg")), structure(c(2.4076232,
49.00203584), class = c("XY", "POINT", "sfg")), structure(c(2.33267081,
48.84896818), class = c("XY", "POINT", "sfg")), structure(c(2.32290084,
49.02966528), class = c("XY", "POINT", "sfg")), structure(c(2.53124065,
48.938607), class = c("XY", "POINT", "sfg")), structure(c(2.07605224,
48.77307843), class = c("XY", "POINT", "sfg")), structure(c(2.16026445,
48.84105162), class = c("XY", "POINT", "sfg"))), class = c("sfc_POINT",
"sfc"), precision = 0, bbox = structure(c(xmin = 2.05650642,
ymin = 48.75044317, xmax = 2.53124065, ymax = 49.02966528
), class = "bbox"), crs = structure(list(epsg = 4326L, proj4string = "+proj=longlat
+datum=WGS84 +no_defs"), class = "crs"), n_empty = 0L)), sf_column = "geometry", agr
= structure(c(ID = NA_integer_,
n = NA_integer_), .Label = c("constant", "aggregate", "identity"
), class = "factor"), row.names = c(380L, 433L, 312L, 257L, 464L,
6L, 457L, 364L, 156L, 341L), class = c("sf", "data.frame"))
getImage <- function(n, ncol=10, proba = 1) {
require(ggthemes)
require(ggplot2)
require(dplyr)
num <- 1:n
x <- num%%ncol
y <- num%/%ncol
df <- data.frame(x=x,y=y)
df[nrow(df),] <- c(0,0)
df <- df %>% arrange(y,x)
df$dispo <- as.factor(c(rep(1,round(n*proba)),rep(0,(n-round(n*proba)))))
ymax <- ifelse(n>ncol*10,n/ncol+1,ncol+1)
#if we have a few points, let's center them
if (n< ncol*10) df$y <- df$y + (ncol-(max(df$y)))/2
g<- ggplot(df,aes(x=x,y=y, color=dispo))+
# geom_point(shape="\UC6C3", colour="red",size=5)+
geom_point(size=10,show.legend = F)+
xlim(-1,ncol+1) + ylim(-1,ymax)+
theme_void()+
scale_fill_manual(values = c("green", "red"))
g
}
plots <- lapply(employees_spdf$n,function(x) getImage(x,proba = .66))
for (i in 1:nrow(employees_spdf)) {
filename <- paste("./tmp/",employees_spdf[i,]$ID,".png",sep="")
ggsave(filename = filename,
plot = plots[[i]],
device = "png",
width = 5, height = 5,
units = "in", bg="transparent")}
filenames <- unlist(lapply(employees_spdf$ID, function(x) paste(paste("./tmp/",x,".png",sep=""))))
empIcons <- icons(
iconUrl = filenames,
iconWidth = 128,
iconHeight = 128
)
leaflet() %>%
addTiles() %>%
addMarkers(data=employees_spdf,
icons=empIcons)
The bottleneck here is eventually a need to save each ggplot as a file, read it and then use it as an icon. For 500+ subregions it takes quite a while to load...
The core of the issue as far as I undesrtand is that a leaflet MakeIcon function can work only whith files and I cannot pass a list of ggplot objects to it. That way it would have worked much faster I believe...
The solution here could be saving a ggplot for each region before the application loads and read them on the fly, however I thought there might be a more elegant option. Do you know one?