Diagram with arranged countries polygons - r

I am looking for solution of a special diagram using following data set (below). The diagram has to contain the polygons of the countries from the data set, but they have to be (1) placed next to each other, not by long,lat coordinates; (2) the size of the polygon of the each country has to correspond to the relative size, which is a t$rs variable (calculated as it's shown below); (3) the fill color of each country depends on the value of t$value variable -- if it's positive the color is green and red if negative.
My code so far is:
library(ggmap)
library(dplyr)
library(sf)
library(tidyverse)
library(gridExtra)
library(rgdal)
library(tmap)
# The data set
t <- data.frame(id = c(136,142,172,567),
name = c("Italy","Norway","Finland","Singapore"),
value = c(-0.921253632,245.6713064,4.049413648,207.5896534))
# Min value in absolute terms
min = min(abs(t$value))
# Relative value w.r.t. min value
t$rs <- t$value / min
# Shape files for countries
# https://hub.arcgis.com/datasets/esri::world-countries-generalized/about
# Unzip files from the ArcGIS archive file
unzip("World_Countries_(Generalized).zip", exdir = ".")
shp.file <- "World_Countries__Generalized_.shx"
countries <- readOGR(shp.file)
qtm(countries[countries$COUNTRY %in% t$name,])
My output diagram is attached. It's a bit far from desired shape.

I adjusted your data import slightly using st_read() from the sf package:
library(tidyverse)
library(sf)
library(tmap)
# Unzip files from the ArcGIS archive file
unzip("World_Countries_(Generalized).zip", exdir = ".")
shp.file <- "World_Countries__Generalized_.shx"
countries <- st_read(shp.file)
countries %>%
left_join(t, by = c("COUNTRY" = "name")) %>%
filter(!is.na(id)) %>%
st_as_sf() %>%
tm_shape() +
tm_fill("value") +
tm_facets(by = "COUNTRY")

Related

What code can I use to count the number of pixels in an image or plot in r studio?

I hope you are great!
I am very beginner to r, and I am having a hard time figuring out two things. The first one is that I need to find the number of pixels I have in an image, which I already look for, but none of the codes work out. For the second part, you will need some context. I am working on getting the ndvi -and other bands- of a furrow-irrigated rice field, which has an upper part and a lower part. I need to divide my image into these parts, the top part, the middle part, and the bottom part. But I can't find a code for that either.
Can someone help me, please?
##Attached is the image I am working on##
##Code I am using##
library(raster)
library(cowplot)
library(tidyverse)
library(ggsn)
library(ggpubr)
library(sf)
library(ggplot2)
library(ggpubr)
library(gridExtra)
library(grid)
library(rgdal)
library(sf)
require(raster)
grey <- raster("SentFurrowField2021WB.tif")
load.image("SentFurrowField2021WB.tif")
rgb <- brick(grey)
plot(grey)
getwd()
list.files()
##number of bands in Raster
nbands(grey)
##what are the bands
bandnr(grey)
View(grey)
library(tidyverse)
band1 <- raster("SentFurrowField2021WB.tif",band =1)
plot(band1)
band1df <- as.data.frame(band1, xy = TRUE) %>% drop_na()
View(band1df)
band1
band2 <- raster("SentFurrowField2021WB.tif", band =2)
band2
plot(band2)
band2df <- as.data.frame(band2, xy = TRUE) %>% drop_na()
View(band2df)
band3 <- raster("SentFurrowField2021WB.tif", band =3)
band3
plot(band3)
band3df <- as.data.frame(band3, xy = TRUE) %>% drop_na()
View(band3df)
band4 <- raster("SentFurrowField2021WB.tif", band =4)
band4
plot(band4)
band4df <- as.data.frame(band4, xy = TRUE) %>% drop_na()
View(band4df)
#names(band2)
#names(band1)
#names(band1df)
library(raster)
#> Loading required package: sp
ggspatial::grey()
##I think this is the plot function that you are currently using
plot(grey)
#you can transform the raster to EPSG:4326 (lat/lon)
grey <- projectRaster(grey, crs = crs("+init=epsg:4326"))
plot(grey)
#you could also use ggspatial + ggplot, which keeps the projection
#but has axis labels in lat/lon
library(ggspatial)
#> Loading required package: ggplot2
ggplot() +
layer_spatial(grey, aes(fill = stat(band1))) +
scale_fill_continuous(na.value = NA)
#> Warning: Removed 8792 rows containing missing values (geom_raster).
[1]: https://i.stack.imgur.com/ymg1x.png

no applicable method for 'summarise' applied to an object of class "c('double', 'numeric')"

Currently, I have a .csv file with a bunch of lat/lon points that have fire radiance (FRP) values associated with each geographic point. What I would like to do is rasterize this CSV, then overlay that with a multipolygon vector layer and extract the average for each individual polygon in that layer. Here is the code I am using the accomplish this task:
library(choroplethr)
library(choroplethrMaps)
library(ggmap)
library(exactextractr) #For `exact_extract`
library(matrixStats) #For `colWeightedMeans`
library(raster) #For `brick`
library(sf) #For `st_read`
library(stringr) #For `str_sub`
library(tidyr)
library(dplyr)
library(RColorBrewer)
library(ncdf4) # package for netcdf manipulation
library(rasterVis)
library(raster) # package for raster manipulation
library(rgdal) # package for geospatial analysis
library(ggplot2) # package for plotting
library(maptools)
library(rgeos)
library(maps)
library(data.table)
library(reshape)
library(doBy)
# TOY .csv file, in real code I load in a much larger file
viirs_2020 <- read.csv(text = "frp, lat, long,
1.43,46.73021,-92.0754,
1.27,46.72907,-92.0775,
1.8,40.72152,-84.1262,
1.23,41.63972,-87.1309,
0.82,41.61905,-87.3285,
1.61,41.64,-87.4095,
1.56,41.64461,-87.141, header=TRUE")
# setting extent + projection for raster data
viirs2020_r <- raster(xmn = -125, xmx = -65, ymn = 15, ymx = 55, res = 0.75, crs = "+proj=longlat +datum=WGS84")
# converting .csv file into a raster
viirs2020_raster <- rasterize(viirs_2020[, c('long', 'lat')], viirs2020_r, viirs_2020[, 'frp'], fun=mean)
plot(viirs2020_raster)
# Load in shapefile which is a grid over a wildfire
cp_grid <- st_read('Drop Effectiveness/data/map data/cameronpeak_grid.shp')
cp_grid <- st_transform(cp_grid, 4269)
cp_grid$id <- factor(cp_grid$id)
#Function for taking the mean of values within shapes in coverage
get_frp = function(values, coverage){
values %>% summarize(across(everything(), ~ weighted.mean(.x, coverage, na.rm=TRUE)))
}
###extract the averages
out = exact_extract(viirs2020_raster, cp_grid, fun=get_frp, stack_apply=FALSE)
I've managed to do this successfully using the exact_extract function with NetCDF files in the past on different projects. But when I attempt to perform this task with the rasterized .csv file, I get the following error on the final line of the code I pasted above:
"in UseMethod("summarise") :
no applicable method for 'summarise' applied to an object of class "c('double', 'numeric')"
Anyone have an idea what could be causing this error?
I was unable to figure out how to solve this problem by changing the custom function that I wrote. However, I was able to replicate the process by doing a simple 'exact_extract' first, then calculate the weighted mean afterward.
out = exact_extract(viirs2020_raster, cp_grid)
# Create data frame from extraction
frp_combined <- bind_rows(out, .id = "id") %>%
as_tibble()
# Create a weighted mean based on values and coverage of raster
frp_by_id <- frp_combined %>%
#--- convert from character to numeric ---#
mutate(id = as.numeric(id)) %>%
#--- group summary ---#
group_by(id) %>%
summarise(frp_aw = sum(value * coverage_fraction) / sum(coverage_fraction))
# Merge extracted values to each polygon
cameronpeak.frp <- cp_grid %>%
mutate(id := seq_len(nrow(.))) %>%
left_join(., frp_by_id, by = "id") %>%
dplyr::select(id, frp_aw)
I think the he problem comes from the lack of {{ }} to wrap the variable name coverage.
Try the following
#Function for taking the mean of values within shapes in coverage
get_frp = function(values, coverage){
values %>% summarize(across(everything()), ~ weighted.mean(.x, {{coverage}}, na.rm=TRUE))
}
More info on this : https://rlang.r-lib.org/reference/topic-metaprogramming.html

Putting Values on a County Map in R

I am using an excel sheet for data. One column has FIPS numbers for GA counties and the other is labeled Count with numbers 1 - 5. I have made a map with these values using the following code:
library(usmap)
library(ggplot2)
library(rio)
carrierdata <- import("GA Info.xlsx")
plot_usmap( data = carrierdata, values = "Count", "counties", include = c("GA"), color="black") +
labs(title="Georgia")+
scale_fill_continuous(low = "#56B1F7", high = "#132B43", name="Count", label=scales::comma)+
theme(plot.background=element_rect(), legend.position="right")
I've included the picture of the map I get and a sample of the data I am using. Can anyone help me put the actual Count numbers on each county?
Thanks!
Data
The usmap package is a good source for county maps, but the data it contains is in the format of data frames of x, y co-ordinates of county outlines, whereas you need the numbers plotted in the center of the counties. The package doesn't seem to contain the center co-ordinates for each county.
Although it's a bit of a pain, it is worth converting the map into a formal sf data frame format to give better plotting options, including the calculation of the centroid for each county. First, we'll load the necessary packages, get the Georgia data and convert it to sf format:
library(usmap)
library(sf)
library(ggplot2)
d <- us_map("counties")
d <- d[d$abbr == "GA",]
GAc <- lapply(split(d, d$county), function(x) st_polygon(list(cbind(x$x, x$y))))
GA <- st_sfc(GAc, crs = usmap_crs()#projargs)
GA <- st_sf(data.frame(fips = unique(d$fips), county = names(GAc), geometry = GA))
Now, obviously I don't have your numeric data, so I'll have to make some up, equivalent to the data you are importing from Excel. I'll assume your own carrierdata has a column named "fips" and another called "values":
set.seed(69)
carrierdata <- data.frame(fips = GA$fips, values = sample(5, nrow(GA), TRUE))
So now we left_join our imported data to the GA county data:
GA <- dplyr::left_join(GA, carrierdata, by = "fips")
And we can calculate the center point for each county:
GA$centroids <- st_centroid(GA$geometry)
All that's left now is to plot the result:
ggplot(GA) +
geom_sf(aes(fill = values)) +
geom_sf_text(aes(label = values, geometry = centroids), colour = "white")

R:How to display city level data on map and how to ZOOM it on one specific region of the map

I am using usmap and ggplot to plot population on a map. My data has two columns - population and zipcodes.
Question: How can I display data on city level using the same libraries or if you know of other libraries that can do the job.
Question: I am plotting California map and I want to zoom on LA county and nearby counties.
Below code gives me a nice California map and population as a color.
library(usmap)
library(ggplot2)
usmap::plot_usmap("counties",
include = ("CA") )
plot_usmap(data = data, values = "pop_2015", include = c("CA"), color = "grey") +
theme(legend.position = "right")+scale_fill_gradient(trans = "log10")
The tigris package makes downloading zip code tabulation areas fairly simple. You can download as a simple features dataframe so joining your data by zip code using dplyr functions is fairly easy. Here is a quick example:
library(tigris)
library(dplyr)
library(ggplot2)
df <- zctas(cb = TRUE,
starts_with = c("778"),
class = "sf")
## generate some sample data that
## can be joined to the downloaded data
sample_data <- tibble(zips = df$ZCTA5CE10,
values = rnorm(n = df$ZCTA5CE10))
## left join the sample data to the downloaded data
df <- df %>%
left_join(sample_data,
by = c("ZCTA5CE10" = "zips"))
## plot something
ggplot(df) +
geom_sf(aes(fill = values))

Keep getting NAs when I run Over() function on Points(Lat,Lon) on shapefile polygons

I am not sure why i am keep getting NA whenever I run the Over function with Latitude and Longitude point on the polygon from shapefile. Please note that this is first time for me doing the spatial analysis, but I have done my research and replicated things, but didn't succeed. I need some points which are outside of the polygon to be NA, so I can focus on the real data.
I read these sources since these pertain to my cause but I can't work my problem out:
sp::over() for point in polygon analysis
https://gis.stackexchange.com/questions/133625/checking-if-points-fall-within-polygon-shapefile
https://gis.stackexchange.com/questions/278723/r-error-in-checking-point-inside-polygon
Here is my code chunk
library(sp)
library(rgdal)
library(readr)
gainsville_df <- read_csv("311_Service_Requests__myGNV_.csv")
gnv <- readOGR("~\\Downloads\\GIS_cgbound", layer = "cgbound")
gnv_latlon <- spTransform(gnv, CRS("+proj=longlat +ellps=WGS84 +datum=WGS84"))
gnv_raw <- data.frame(Longitude= gainsville_df$Longitude, Latitude= gainsville_df$Latitude)
coordinates(gnv_raw) <- ~Longitude + Latitude
proj4string(gnv_raw) <- proj4string(gnv)
over(gnv_raw, as(gnv,"SpatialLinesDataFrame"))
#Yeilds:
# FID_cgboun Id Perimeter Area Acres Hectares Shape_Leng
#1 NA NA NA NA NA NA NA
# Desired Output:
# Whereas I should have seen which gainesville Latitudes and Longitude are within the shpaefile
# polygon so I can drop the outliers, that have the NA. According to this, none of my LatLon points
# are inside the polygon.
The datafiles are here:
Shapefile: https://github.com/THsTestingGround/SO_readOGR_quest/tree/master/GIS_cgbound
reading csv file: https://github.com/THsTestingGround/SO_readOGR_quest/blob/master/311_Service_Requests__myGNV_.csv
I would appreciate if someone can help me out.
I realized that your point data is an sf object since you have POINT (-82.34323174 29.67058748) as character. Hence, I reconstructed your data first. I assigned a projection here as well.
library(tidyverse)
library(sf)
library(RCurl)
url <- getURL("https://raw.githubusercontent.com/THsTestingGround/SO_readOGR_quest/master/311_Service_Requests__myGNV_.csv")
mydf <- read_csv(url) %>%
mutate(Location = gsub(x = Location, pattern = "POINT \\(|\\)", replacement = "")) %>%
separate(col = "Location", into = c("lon", "lat"), sep = " ") %>%
st_as_sf(coords = c(3,4)) %>%
st_set_crs(4326)
I imported your shapefile using sf package since your data (mydf in this demonstration) is an sf object. When I imported the data, I realized that I had LINESTRING, not polygons. I believe this is the reason why over() did not work. Here I created polygons. Specifically, I joined all seven polygons all together.
mypoly <- st_read("cgbound.shp") %>%
st_transform(crs = 4326) %>%
st_polygonize() %>%
st_union()
Let's check how your data points and polygon are like. You surely have data points staying outside of the polygon.
ggplot() +
geom_sf(data = mypoly) +
geom_point(data = mydf, aes(x = Longitude, y = Latitude))
You said, "I need some points which are outside of the polygon to be NA." So I decided to create a new column in mydf using st_intersects(). If a data point stays in the polygon, you see TRUE in the new column, check. Otherwise, you see FALSE.
mutate(mydf,
check = as.vector(st_intersects(x = mydf, y = mypoly, sparse = FALSE))) -> result
Finally, check how data points are checked.
ggplot() +
geom_sf(data = mypoly) +
geom_point(data = result, aes(x = Longitude, y = Latitude, color = check))
If you wanna use over() mixing with this sf way, you can do the following.
mutate(mydf,
check = over(as(mydf, "Spatial"), as(mypoly, "Spatial")))
The last thing you wanna do is to subset the data
filter(result, check == TRUE)
THE SIMPLEST WAY
I demonstrated you how things are working with this sf approach. But the following is actually all you need. st_filter() extracts data points staying in mypoly. In this case, data points staying outside are removed. If you do not have to create NAs for these points, this is much easier.
st_filter(x = mydf, y = mypoly, predicate = st_intersects) -> result2
ggplot() +
geom_sf(data = mypoly) +
geom_sf(data = result2)

Resources