Been a while since I've blogged here; wrapping up an MSc and moving continents from Europe to North America is all the excuse I need. This blog post is not going to be revolutionary, and obviously it builds on a lot of what others have done before (see towards the end) but I hope enough people find it fun and perhaps informative.
So I've bitten the bullet and emigrated to Edmonton, Alberta (that's the Canadian province just to the east of British Columbia, and to the west of Saskatchewan--north of Idaho, where they grow the potatoes, if you like). I've been pleasantly surprised by the number of individuals I've met with a positive outlook on renewables--this is a bit of a relief, when we landed in Canada and quarantined in Calgary, it felt like I was being bombarded with all sorts of messaging which was pro-oil and gas (read: climate denialist). In fact, there's some data to indicate that the anti-renewables crowd are not representative of Alberta--the "Saudi Arabia of Canada"-- at all. Institutionally, I've also enjoyed reading the output from the Pembina Institute, which seems to specialise in "blue skies optimism" backed up by solid research.
For those who don't know: the cold temperatures and high levels of solar insolation are a perfect mix for solar PV panels. I was particularly drawn to these heat maps drawn up by Pembina's Binnu Jeyakumar: https://www.pembina.org/blog/unlocking-renewables-will-unlock-jobs-alberta At the time I first saw them late last year, I was stuck in finishing my thesis, but now that I've got the time, I'm going to try and replicate one of these maps in R. When finished, I will have drawn a heat map in R which illustrates the differences in solar insolation at "Census Division" level across the Province of Alberta.
When we're done, this is what the map of Alberta is going to look likeLet's start at the beginning. In general, countries have multiple levels of provincial government. For example, any neighborhood in Canada is going to have three layers/levels of government: a Federal government, based in Ottawa, Level 0; a pronvincial government, let's say Alberta, which is Level 1; and a municipal government, with a town council and the like. Let's say we start with Edmonton, which in this case is going to be Level 2. What does a map of Canada look like at that level of granularity? First, download the data from GADM as follows. I also download Level 1 and Level 2 :
library(rgeos) library(maptools) library(ggmap) library(ggplot2) library(sp) library(rgdal) library(raster) #Various packages for GIS and mapping library(plyr) #This one is for database manipulations like "join" library(nasapower) #To get the solar insolation and other meteorological data library(scales) #This one allows us to do things like have nice scales for the legends on the images we create #Download the files for Levels 1 and 2 SPDFs covering Canada can_level1 = getData("GADM", country = "CA", level = 1) can_level2 = getData("GADM", country = "CA", level =2)
plot(can_level1, col = "pink", bg = "lightblue")
> names(can_level1) [1] "GID_0" "NAME_0" "GID_1" "NAME_1" "VARNAME_1" "NL_NAME_1" "TYPE_1" [8] "ENGTYPE_1" "CC_1" "HASC_1"
> can_level1$NAME_1 [1] "Alberta" "British Columbia" "Manitoba" [4] "New Brunswick" "Newfoundland and Labrador" "Northwest Territories" [7] "Nova Scotia" "Nunavut" "Ontario" [10] "Prince Edward Island" "Québec" "Saskatchewan" [13] "Yukon"
> alberta_level1 = can_level1[which(can_level1$NAME_1 == "Alberta"),]
> plot(alberta_level1, col = "green", add = TRUE)
WGS84 <- CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs") canada_level2_ellipsoid = spTransform(can_level2, WGS84)
alberta_ellipsoid = canada_level2_ellipsoid[which(canada_level2_ellipsoid$NAME_1 == "Alberta"),]
alberta_coordinates = data.frame(matrix(ncol = 2, nrow = length(alberta_ellipsoid$NAME_2))) for(i in 1:length(alberta_ellipsoid$NAME_2)) { alberta_coordinates[i,] = data.frame(gCentroid(alberta_ellipsoid[i,])) }
ghi_retrieved = nasapower::get_power(community = "SSE", pars = "ALLSKY_SFC_SW_DWN", lonlat = c(alberta_coordinates[1,1], alberta_coordinates[1,2]), temporal_average = "CLIMATOLOGY")
Here, "ALLSKY_SFC_SW_DWN" retrieves the GHI or "Global Horizontal Irradiation; and "Climatology" defines the inbuilt timeframe from 1-1-1984 to 31-12-2013. One important thing you'll notice is that the average daily insolation on a GHI basis is stored in column 16 of the returned data.frame (actually a tibble in the first instance from the above line). So we will build an all-Alberta data frame containing the average yearly insolation during the "CLIMATOLOGY" timeframe thus:
alberta_solar_insolation_annual = data.frame(matrix(ncol = 1, nrow = nrow(alberta_coordinates))) for(i in 1:nrow(alberta_coordinates)) { ghi_retrieved = nasapower::get_power(community = "SSE", pars = "ALLSKY_SFC_SW_DWN", lonlat = c(alberta_coordinates[i,1], alberta_coordinates[i,2]), temporal_average = "CLIMATOLOGY") alberta_solar_insolation_annual[i,] = data.frame(ghi_retrieved[16])*365 print("One more Census Division") }
alberta_solar_insolation_annual = cbind(unique(alberta_ellipsoid@data$NAME_2), alberta_solar_insolation_annual) #We set also the metadata colnames(alberta_solar_insolation_annual) = c("NAME_2", "Insolation")
alberta_ellipsoid@data
names(alberta_ellipsoid@data) [1] "GID_0" "NAME_0" "GID_1" "NAME_1" "NL_NAME_1" "GID_2" "NAME_2" "VARNAME_2" [9] "NL_NAME_2" "TYPE_2" "ENGTYPE_2" "CC_2" "HASC_2" "GID_0.1" "NAME_0.1" "GID_1.1" [17] "NAME_1.1" "NL_NAME_1.1" "GID_2.1" "VARNAME_2.1" "NL_NAME_2.1" "TYPE_2.1" "ENGTYPE_2.1" "CC_2.1" [25] "HASC_2.1"
alberta_ellipsoid@data = join(alberta_ellipsoid@data, alberta_solar_df, by = "NAME_2") alberta_solar_df_fortified_B = fortify(alberta_ellipsoid)
ggplot() + geom_polygon(data = alberta_solar_df_fortified_B, aes(x = long, y = lat, group = group, fill = Insolation), size = 0.12) + scale_fill_distiller(name="Insolation, annual \n kWh per m^2", palette = "Spectral", breaks = 7)
This looks pretty and all, but it's also not entirely conclusive of anything if it's not put into perspective. So I repeated the steps above, but instead of Level 2 districts in Alberta alone, I mapped them for the two provinces of Western Canada: Alberta and British Columbia, the latter of which is to the west (left) of the image. As can be clearly seen, Alberta is pretty much consistently more sunny than British Columbia.
Coming up in future posts, I will move on to try and map not only insolation but also more decision variable type values, such as PV yield. A yet more sophisticated approach involves also the intermittency of solar PV and how it matches, or doesn't match, electricity demand (i.e., without storage, PV electricity is no good if people only play video games and turn the lights on at night). That's for much later down the road! To see a similar example which I relied on quite a bit in this case, see here about making a country level map with ggplot2: https://rpubs.com/spoonerf/countrymapggplot2