Libraries
#Data Manipulation
library(tidyverse)
#Raster Data Handling
library(raster)
#Keyless Landset Data (2013-2017)
library(getlandsat)
#Rapid Interactive Visualization
library(mapview)
#Vector Data Processing
library(sf)
library(osmdata)
#
library(USAboundaries)
library(rnaturalearth)
library(rmapshaper)
library(readxl)
library(gghighlight)
library(ggrepel)
library(knitr)
library(ggthemes)
library(leaflet)
library(leafpop)
library(units)
Question 1:
bb = read_csv("../data/uscities.csv") %>%
filter(city == "Palo") %>%
st_as_sf(coords = c("lng", "lat"), crs = 4326) %>%
st_transform(5070) %>%
st_buffer(5000) %>%
st_bbox() %>%
st_as_sfc() %>%
st_sf()
Question 2:
meta = read_csv("../data/palo-flood.csv")
files = lsat_scene_files(meta$download_url) %>%
filter(grepl(paste0("B", 1:6, ".TIF$", collapse = "|"), file)) %>%
arrange(file) %>%
pull(file)
#"paste0" gives space between columns, "paste" will not give a space.
# We only need "6" bands because they are very large
#for (i in 1:6) download each of these bands for us
st = sapply(files, lsat_image)
# "sapply" is returning a list of vectors (instead of repeating the role 6 times)
s = stack(st) %>%
setNames(c(paste0("band", 1:6)))
# stack(st)
The dimensions of my stacked image are as follows: nrow (7811), ncol (7681), ncell (59,996,291), nlayers (6). The CRS is UTM WGS84 and the cell resolution is 30 x 30 (meters).
cropper = bb %>% st_as_sf() %>% st_transform(crs(s))
r = crop(s, cropper)
# r
The dimensions of my cropped image stacks are as follows: nrow (340), ncol (346), ncell (117,640), nlayers (6). The CRS is UTM WGS84 and the cell resolution is 30 x 30 (meters), which is the same as above.
Question 3:
#Near Infrared (NIR) wavelength is commonly used to analysis vegetation health because vegetation reflects strongly in this portion of the electromagnetic spectrum.
#Shortwave Infrared (SWIR) bands are useful for discerning what is wet and dry.
ras_name = r %>% setNames(c("coastal", "blue", "green", "red", "NIR", "SWIR 1"))
#R_G_B (natural color)
plotRGB(ras_name, r = 4, g = 3, b = 2)
#NIR_R_G (fa)(color infrared)
plotRGB(ras_name, r = 5, g = 4, b = 3)
#NIR_SWIR1_R (false color water focus)
plotRGB(ras_name, r = 5, g = 6, b = 4)
# (false color urban focus)
plotRGB(ras_name, r = 7, g = 6, b = 4)
par(mfrow = c(2,2))
#R_G_B (natural color)
plotRGB(ras_name, r = 4, g = 3, b = 2, stretch = "lin")
#NIR_R_G (fa)(color infrared)
plotRGB(ras_name, r = 5, g = 4, b = 3, stretch = "lin")
#NIR_SWIR1_R (false color water focus)
plotRGB(ras_name, r = 5, g = 6, b = 4, stretch = "lin")
# (false color urban focus)
plotRGB(ras_name, r = 7, g = 6, b = 4, stretch = "lin")
par(mfrow = c(2,2))
#R_G_B (natural color)
plotRGB(ras_name, r = 4, g = 3, b = 2, stretch = "hist")
#NIR_R_G (fa)(color infrared)
plotRGB(ras_name, r = 5, g = 4, b = 3, stretch = "hist")
#NIR_SWIR1_R (false color water focus)
plotRGB(ras_name, r = 5, g = 6, b = 4, stretch = "hist")
# (false color urban focus)
plotRGB(ras_name, r = 7, g = 6, b = 4, stretch = "hist")
The purpose of applying a color stretch is to seperate the variance in color to better show the information that is needed for a project. This helps with seeing and understanding patterns within a given landscape.
Question 4:
#Raster Algebra
#Normalized difference vegetation index
NDVI = (r$band5 - r$band4)/(r$band5 + r$band4)
#plot(NDVI)
#Normalized Difference Water Index
NDWI = (r$band3 - r$band5)/(r$band3 + r$band5)
#Modified, normalized difference water index
MNDWI = (r$band3 - r$band6)/(r$band3 + r$band6)
#Water ratio index
WRI = (r$band3 + r$band4)/(r$band5 + r$band6)
#Simple water index
SWI = 1/(sqrt(r$band2 - r$band6))
ras_stack = stack(NDVI, NDWI, MNDWI, WRI, SWI) %>%
setNames(c("NDVI", "NDWI", "MNDWI", "WRI", "SWI"))
palette = colorRampPalette(c("blue", "white", "red"))
plot(ras_stack, col = palette(256))
The images appear to deviate based on placement and quanity of blue, white, and red. For example, NDVI & SWI show the water as blue, but they differ in that SWI appears void of the color red. Another example, NDWI, MNDWI, and WRI all show the water as red, but they differ in amount of white versus blue. Additionally, all five maps have a different scale level and axis labels.
# Raster Thresholding
thres_NDVI = function(x){ifelse(x <= 0,1,0)}
thres_NDWI = function(x){ifelse(x >= 0,1,0)}
thres_MNDWI = function(x){ifelse(x >= 0,1,0)}
thres_WRI = function(x){ifelse(x >= 1,1,0)}
thres_SWI = function(x){ifelse(x <= 5,1,0)}
calc_NDVI = calc(NDVI, thres_NDVI)
calc_NDWI = calc(NDWI, thres_NDWI)
calc_MNDWI = calc(MNDWI, thres_MNDWI)
calc_WRI = calc(WRI, thres_WRI)
calc_SWI = calc(SWI, thres_SWI)
flood = stack(c(calc_NDVI, calc_NDWI, calc_MNDWI, calc_WRI, calc_SWI)) %>%
setNames(c("NDVI", "NDWI", "MNDWI", "WRI", "SWI"))
palette_fld = colorRampPalette(c("white", "blue"))
plot(flood, col = palette_fld(256))
Question 5:
set.seed(09072020)
values_g = getValues(r)
dim(values_g)
## [1] 117640 6
There is one data set (matrix?) with the size of 59,996,291 and 6 layers.
values_g = na.omit(values_g)
v5 = scale(values_g)
E5 = kmeans(v5, 12, iter.max = 100)
kmeans_raster = flood$NDVI
values(kmeans_raster) = E5$cluster
plot(kmeans_raster)
E6 = kmeans(v5, 6, iter.max = 100)
kmeans_raster_6 = flood$NDVI
clus_5 = values(kmeans_raster_6) = E6$cluster
plot(kmeans_raster_6)
E3 = kmeans(v5, 3, iter.max = 100)
kmeans_raster_3 = flood$NDVI
values(kmeans_raster_3) = E3$cluster
plot(kmeans_raster_3)
table = table(getValues(calc_MNDWI), getValues(kmeans_raster_6))
which.max(table)
## [1] 5
thres_MNDWI_5 = function(x){ifelse(x == 3,1,0)}
#calc_MNDWI = calc(MNDWI, thres_MNDWI)
calc_5 = calc(kmeans_raster_6, thres_MNDWI_5) %>% setNames(c('most flooded'))
layer_5 = addLayer(flood, calc_5)
palette_calc_5 = colorRampPalette(c("white", "blue"))
plot(layer_5, col = palette_calc_5(256))
Question 6:
total_area = cellStats(flood_5, sum)
knitr::kable(total_area, caption = "Flooded Area: Cells", col.names = c("cells"))
Flooded Area: Cells
NDVI |
6666 |
NDWI |
7212 |
MNDWI |
11939 |
WRI |
8469 |
SWI |
15201 |
most.flooded |
596 |
total_area_2 = total_area * (900)
knitr::kable(total_area_2, caption = "Flooded Area: Area", col.names = c("Area m2"))
Flooded Area: Area
NDVI |
5999400 |
NDWI |
6490800 |
MNDWI |
10745100 |
WRI |
7622100 |
SWI |
13680900 |
most.flooded |
536400 |
flood_6 = calc(layer_5, function(x){sum(x)})
plot(flood_6, col = blues9)
cell_val = ifelse(values(layer_5) ==0, NA, values(layer_5))
mapview(flood_6)
### The cell values are not an even number because they are combined to geo map data scale.
Five of the six maps captured the flooding in Palo, Iowa (coordinates -91.789504, 42.063058). Luckly, it appears that this was a vacant lot.