I'm making a Leaflet map in R and I want to assign certain data to the specific areas. Right now I'm using a placeholder just to try and figure it out but I'm not having luck. I have certain data from an excel file that I want to assign to certain counties. How would I go about that?
library(maptools)
library(leaflet)
library(rjson)
library(magrittr)
library(sf)
library(xlsx)
## reads in the JSON data of all counties in USA
counties <- sf::read_sf("http://eric.clst.org/wupl/Stuff/gz_2010_us_050_00_500k.json")
## selects kansas and missouri county lines
kscounties<-counties[counties$STATE=="20",]
mocounties<-counties[counties$STATE=="29",]
## variable containing all kansas and missouricounty names
kscountynames<-kscounties$NAME
mocountynames<-mocounties$NAME
## combines both counties
bothcounties<-rbind(kscounties,mocounties)
bothcountynames<-c(kscountynames,mocountynames)
## color pallette
pal<-colorNumeric("viridis",NULL)
## placeholder
percent=c(1:100)
## creates leaflet of kansas and missouri counties
leaflet(bothcounties) %>%
addTiles() %>%
addPolygons(stroke = FALSE, smoothFactor = 0.3, fillOpacity = 1,
fillColor = ~pal(percent),
label = ~paste(bothcountynames, "\n", formatC(percent, big.mark = ",")
)) %>%
setView(-98.4,38.5,zoom=6) %>%
addLegend(position="bottomright",pal = pal, values = percent, opacity = 1.0,title="Percent") %>%
addLayersControl(position="topleft",
baseGroups = c("1","2"),
overlayGroups=c("A","B","C","D","E","F")
)
You can just create a separate dataframe containing the data in question and refer to it when plotting. You just have to be careful to ensure the order of counties in the dataframe matches the order of counties in the geo-data. The county names you're already extracting should work as a 'key' to match that order.
From your code above, change the #placeholder part to..
data_to_plot <- data.frame("NAME"=bothcountynames,"data"=###YOURDATA_IN_CORRECT_ORDER###))
..with the data you want to plot. You could also just set-up a single-column dataframe with the names and then do a merge/join as it may be an easier way to maintain the required order.
In the leaflet call, put fillColor = pal(data_to_plot$data). The ~ basically won't be necessary if the data you're referencing is stored in a separate object.
Related
I am working with ISO-3 names of the countries. Below you can see one example.I want to use this data for Choropleth map.
datar <- data.frame(GEO = c("GR","AZ","TR","GA","IR"),
Value = c(0.5560,0.323,0.2140,0.312,0.0225),
search_countries = factor(c("Greece","Azerbaijan","Turkey","Georgia","Iran")),
countries = c("Greece","Azerbaijan","Turkey","Georgia","Iran")
)
map <- map_data('world', region = datar$search_countries)
The code's last line allows me to draw a Choropleth map. Now I want to have an additional column with the continent names for each country next to the column subregion.
So can anybody help me how to solve this problem and to have a continent name for each country on the table?
If I understand correctly you want to add a column containing the relevant continents for each country in your dataframe?
Here we can get the country and continent names using the raster package then join them onto your dataframe :)
country.codes <- raster::ccodes()
map.continents <- left_join(map, country.codes, by = c('region' = 'NAME')) %>%
select(all_of(colnames(map)), continent)
I have the present shapefile
heitaly<- readOGR("ProvCM01012017/ProvCM01012017_WGS84.shp")
FinalData<- merge(italy, HT, by.x="COD_PROV", by.y="Domain")
But I'm interesting not on all Italy, but also same provinces. How can I get them?
There are many ways to select a category into a shapefile. I don't know for what do you want. For example if it is to colour a specific region in a plot or to select a row from shapefile attribute table.
To plot:
plot(shape, col = shape$column_name == "element") # general example
plot(heitaly, col = heitaly$COD_PROV == "name of province") # your shapefile
To attribute table:
df <- shape %>% data.frame
This will give you the complete attribute table
row <- shape %>% data.frame %>% slice(1)
This will give you the first row with all columns. If you change the number 1 to another number, for example 3, will give you the information for row number 3
I hope have been useful
This is a short one (I hope). I'm trying to plot bicycle routes in my city with leaflet. But addPolylines() does not like my code. What's the problem here?
api.velo.basel <- "https://data.bs.ch/api/records/1.0/search/?dataset=100032&q=&rows=21"
json.velorouten.basel <- read_json(api.velo.basel)
df.routen <- data.frame(do.call(rbind, json.velorouten.basel[["records"]][[2]][["fields"]][["geo_shape"]][["coordinates"]]))
x <- leaflet() %>%
addTiles() %>%
addPolylines(data = df.routen, lng = ~X1, lat = ~X2)
The problem is that the coordinates are given as list of lists and not as list of numeric. So the produced data.frame has columns of type list and not of type numeric.
You need an additional unlist for each coordinate to get standard numeric columns:
df.routen <- data.frame(do.call(rbind, lapply(json.velorouten.basel[["records"]][[2]][["fields"]][["geo_shape"]][["coordinates"]], unlist)))
Alternatively (and probably more efficient) you can also apply unlist to the columns of the data.frame you built.
I'm unable to add a numeric variable in a data frame object to an SF object containing polygons. So, I can't create my map with Ggplot2.
Any help would be very appreciated...
Thanks a lot
Richard
The {sf} objects are modified data frames. There is one column, usually the last, that contains geometry and is mostly hidden + there is some special sauce about coordinate reference systems and so on. But the gist is a data frame (unlike the earlier {sp} objects, but I digress).
As such the {sf} data frames lend themselves easily to data joining techniques, such as dplyr::left_join() used in code example below.
library(sf)
library(dplyr)
library(ggplot2)
shape <- st_read(system.file("shape/nc.shp", package="sf")) # included with sf package
# just some semi - random data
# county with ID 2041 is Mecklenburg (as in Charlotte of Mecklenburg-Strelitz)
some_values <- data.frame(ID = c(2041),
value = c(1))
# left is usually safer than inner join as it does not filter rows
mod_shape <- shape %>%
left_join(some_values, by = c("CNTY_ID" = "ID"))
ggplot(data = mod_shape) +
geom_sf(aes(fill = value)) # viola! a polygon of North Carolina
After going through the highcharter package documentation, visiting JBKunst his website, and looking into list.parse2(), I still can not solve the problem. Problem is as follows: Looking to chart multiple series from a data.frame into a stacked barchart, series can be anywhere from 10 - 30 series. For now the series have been defined as below, but clearly there has to be an easier way, for example passing a list or melted data.frame to the function hc_series similar as what can be done with ggplot2.
Below the code with dummy data
mydata <- data.frame(A=runif(1:10),
B=runif(1:10),
C=runif(1:10))
highchart() %>%
hc_chart(type = "column") %>%
hc_title(text = "MyGraph") %>%
hc_yAxis(title = list(text = "Weights")) %>%
hc_plotOptions(column = list(
dataLabels = list(enabled = FALSE),
stacking = "normal",
enableMouseTracking = FALSE)
) %>%
hc_series(list(name="A",data=mydata$A),
list(name="B",data=mydata$B),
list(name="C",data=mydata$C))
Which produces this chart:
a good approach to add multiples series in my opinion is use hc_add_series_list (oc you can use a for loop) which need a list of series (a series is for example list(name="A",data=mydata$A).
As you said, you need to melt/gather the data, you can use tidyr package:
mynewdata <- gather(mydata)
Then you'll need to group the data by key argument to create the data for each key/series. Here you can use dplyr package:
mynewdata2 <- mynewdata %>%
# we change the key to name to have the label in the legend
group_by(name = key) %>%
# the data in this case is simple, is just .$value column
do(data = .$value)
This data frame will contain two columns and the 2nd colum will contain the ten values for each row.
Now you need this information in a list. So we need to parse using list.parse3 instad of list.parse2 beacuse preserve names like name or data.
series <- list.parse3(mynewdata2)
So finally change:
hc_series(list(name="A",data=mydata$A),
list(name="B",data=mydata$B),
list(name="C",data=mydata$C))
by:
hc_add_series_list(series)
Hope this is clear.