Load libraries
library(sp)
library(raster)
library(randomForest)
## randomForest 4.6-12
## Type rfNews() to see new features/changes/bug fixes.
library(rgdal)
## rgdal: version: 1.2-5, (SVN revision 648)
## Geospatial Data Abstraction Library extensions to R successfully loaded
## Loaded GDAL runtime: GDAL 2.0.1, released 2015/09/15
## Path to GDAL shared files: C:/Program Files/R/R-3.3.2/library/rgdal/gdal
## Loaded PROJ.4 runtime: Rel. 4.9.2, 08 September 2015, [PJ_VERSION: 492]
## Path to PROJ.4 shared files: C:/Program Files/R/R-3.3.2/library/rgdal/proj
## Linking to sp version: 1.2-4
Load data
load("data/GewataB1.rda")
load("data/GewataB2.rda")
load("data/GewataB3.rda")
load("data/GewataB4.rda")
load("data/GewataB5.rda")
load("data/GewataB7.rda")
load("data/vcfGewata.rda")
Clean water, clouds and cloud shadow from VCF data
vcfGewata[vcfGewata>100]<-NA
hist(vcfGewata)

Build a brick containing all data
gwt <- brick(GewataB1, GewataB2, GewataB3, GewataB4, GewataB5, GewataB7, vcfGewata)
names(gwt) <- c("band1", "band2", "band3", "band4", "band5", "band7", "vcf")
Assign bands and VCF values to vectors
band1<-gwt.df$band1
band2<-gwt.df$band2
band3<-gwt.df$band3
band4<-gwt.df$band4
band5<-gwt.df$band5
band7<-gwt.df$band7
vcf<-gwt.df$vcf
Visualizing the data and the relationship between bands and VCF tree cover
plot(gwt)

summary(gwt)
## gewataB1 gewataB2 gewataB3 gewataB4 gewataB5 gewataB7
## Min. 89 127 85 598 113 34
## 1st Qu. 326 410 307 2178 1139 491
## Median 373 469 368 2407 1357 618
## 3rd Qu. 441 594 582 2646 1808 1051
## Max. 1545 2220 2865 4903 16000 16000
## NA's 0 0 0 0 0 0
## vcf2000Gewata
## Min. 0
## 1st Qu. 32
## Median 64
## 3rd Qu. 75
## Max. 100
## NA's 13712
hist(gwt)
pairs(gwt)


Creat a lm model
lm1<-lm(vcf~band1+band2+band3+band4+band5+band7)
summary(lm1)
##
## Call:
## lm(formula = vcf ~ band1 + band2 + band3 + band4 + band5 + band7)
##
## Residuals:
## Min 1Q Median 3Q Max
## -58.205 -4.636 0.715 5.211 258.436
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 8.549e+01 5.723e-02 1493.805 <2e-16 ***
## band1 9.291e-02 1.889e-04 491.817 <2e-16 ***
## band2 -1.505e-01 2.353e-04 -639.622 <2e-16 ***
## band3 -2.528e-03 1.698e-04 -14.889 <2e-16 ***
## band4 1.661e-02 2.790e-05 595.378 <2e-16 ***
## band5 -2.006e-02 7.036e-05 -285.119 <2e-16 ***
## band7 2.549e-05 8.969e-05 0.284 0.776
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 8.606 on 1808277 degrees of freedom
## (13712 observations deleted due to missingness)
## Multiple R-squared: 0.8582, Adjusted R-squared: 0.8582
## F-statistic: 1.824e+06 on 6 and 1808277 DF, p-value: < 2.2e-16
From the results, we can see that band 7 is of little importance
in predicting VCF. For instance, if we remove band 7, the resulting
R-squared would still be the same:
summary(lm(vcf~band1+band2+band3+band4+band5))
##
## Call:
## lm(formula = vcf ~ band1 + band2 + band3 + band4 + band5)
##
## Residuals:
## Min 1Q Median 3Q Max
## -58.204 -4.636 0.715 5.211 258.586
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 8.550e+01 5.601e-02 1526.5 <2e-16 ***
## band1 9.291e-02 1.876e-04 495.3 <2e-16 ***
## band2 -1.505e-01 2.314e-04 -650.5 <2e-16 ***
## band3 -2.504e-03 1.473e-04 -17.0 <2e-16 ***
## band4 1.661e-02 2.443e-05 679.9 <2e-16 ***
## band5 -2.004e-02 4.158e-05 -482.0 <2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 8.606 on 1808278 degrees of freedom
## (13712 observations deleted due to missingness)
## Multiple R-squared: 0.8582, Adjusted R-squared: 0.8582
## F-statistic: 2.189e+06 on 5 and 1808278 DF, p-value: < 2.2e-16
Predict tree cover from model
predTC<- predict(gwt,model=lm1,na.rm=TRUE)
par(mfrow=c(1,1))
predTC[predTC<0]<-NA
plot(predTC,xlim=c(808755,855195),ylim=c(817635,852945))

str(predTC)
## Formal class 'RasterLayer' [package "raster"] with 12 slots
## ..@ file :Formal class '.RasterFile' [package "raster"] with 13 slots
## .. .. ..@ name : chr ""
## .. .. ..@ datanotation: chr "FLT4S"
## .. .. ..@ byteorder : chr "little"
## .. .. ..@ nodatavalue : num -Inf
## .. .. ..@ NAchanged : logi FALSE
## .. .. ..@ nbands : int 1
## .. .. ..@ bandorder : chr "BIL"
## .. .. ..@ offset : int 0
## .. .. ..@ toptobottom : logi TRUE
## .. .. ..@ blockrows : int 0
## .. .. ..@ blockcols : int 0
## .. .. ..@ driver : chr ""
## .. .. ..@ open : logi FALSE
## ..@ data :Formal class '.SingleLayerData' [package "raster"] with 13 slots
## .. .. ..@ values : num [1:1821996] 45.7 37.1 32.7 41.8 24.2 ...
## .. .. ..@ offset : num 0
## .. .. ..@ gain : num 1
## .. .. ..@ inmemory : logi TRUE
## .. .. ..@ fromdisk : logi FALSE
## .. .. ..@ isfactor : logi FALSE
## .. .. ..@ attributes: list()
## .. .. ..@ haveminmax: logi TRUE
## .. .. ..@ min : num 0.000956
## .. .. ..@ max : num 97.9
## .. .. ..@ band : int 1
## .. .. ..@ unit : chr ""
## .. .. ..@ names : chr ""
## ..@ legend :Formal class '.RasterLegend' [package "raster"] with 5 slots
## .. .. ..@ type : chr(0)
## .. .. ..@ values : logi(0)
## .. .. ..@ color : logi(0)
## .. .. ..@ names : logi(0)
## .. .. ..@ colortable: logi(0)
## ..@ title : chr(0)
## ..@ extent :Formal class 'Extent' [package "raster"] with 4 slots
## .. .. ..@ xmin: num 808755
## .. .. ..@ xmax: num 855195
## .. .. ..@ ymin: num 817635
## .. .. ..@ ymax: num 852945
## ..@ rotated : logi FALSE
## ..@ rotation:Formal class '.Rotation' [package "raster"] with 2 slots
## .. .. ..@ geotrans: num(0)
## .. .. ..@ transfun:function ()
## ..@ ncols : int 1548
## ..@ nrows : int 1177
## ..@ crs :Formal class 'CRS' [package "sp"] with 1 slot
## .. .. ..@ projargs: chr "+proj=utm +zone=36 +ellps=WGS84 +units=m +no_defs"
## ..@ history : list()
## ..@ z : list()
randomForest model
## Load the calibration points
samples<-readOGR("data/calib.gwt.kml",layer="calib.gwt")
## OGR data source with driver: KML
## Source: "data/calib.gwt.kml", layer: "calib.gwt"
## with 16 features
## It has 2 fields
class(samples)
## [1] "SpatialPointsDataFrame"
## attr(,"package")
## [1] "sp"
## Re-project spatialPointsDataFrame
samples2<-spTransform(samples,CRS(proj4string(gwt)))
samples2@coords<-coordinates(samples2)[,-3]
## Extract the surface reflectance
calib<- extract(gwt,samples2,df=TRUE)
## Combine the created DF to the description columm of the calibration dataset
calib2<- cbind(samples2$Description,calib)
calib2<-na.omit(calib2)
str(calib2)
## 'data.frame': 13 obs. of 9 variables:
## $ samples2$Description: Factor w/ 3 levels "crop","forest",..: 2 2 1 1 1 2 2 3 3 2 ...
## $ ID : int 1 2 3 4 5 6 7 8 9 10 ...
## $ band1 : int 475 380 565 530 593 424 396 458 546 382 ...
## $ band2 : int 517 489 786 677 737 489 501 613 710 414 ...
## $ band3 : int 393 307 784 748 874 347 378 516 696 339 ...
## $ band4 : int 3027 2685 2364 2274 1923 2946 2632 2764 2352 2811 ...
## $ band5 : int 1414 1267 2709 2486 2160 1416 1240 1537 1943 1453 ...
## $ band7 : int 595 518 1773 1565 1610 570 595 724 1052 592 ...
## $ vcf : int 70 65 12 14 25 70 67 33 29 68 ...
## - attr(*, "na.action")=Class 'omit' Named int [1:3] 13 14 15
## .. ..- attr(*, "names")= chr [1:3] "13" "14" "15"
Calibrate a random forest model using the extracted data frame
rFm<- randomForest(vcf~band1+band2+band3+band4+band5+band7,data=calib2)
Use the model to predict tree cover
tcMap<-predict(gwt,model=rFm)
plot(tcMap)

Function to compute the RMSE
RMSE<-function(x,y) {
sqrt(mean((y-x$vcf)^2,na.rm=TRUE))
}
## Compute the RMSE for the lm model
predTC.df<-as.data.frame(getValues(predTC))
RMSE(gwt.df,predTC.df)
## [1] 8.356825
## Compute the RMSE for the random forest model
tcMap.df<-as.data.frame(getValues(tcMap))
RMSE(gwt.df,tcMap.df)
## [1] 9.259979
Compute RMSE for each class
## Make an NA-value raster based on the LC raster attributes
formask <- setValues(raster(samples2), NA)
## Assign 1 to formask to all cells corresponding to the forest class
formask[samples2$Description=="forest"] <- 1
## Create a grass mask
grassmask <- setValues(raster(samples2), NA)
grassmask[samples2$Description=="grass"] <- 1
##Create a crop mask
cropmask <- setValues(raster(samples2), NA)
cropmask[samples2$Description=="crop"] <- 1
Get values for each class
tcfor<-crop(tcMap,formask)
tcfor.df<-as.data.frame(getValues(tcfor))
tcgrass<-crop(tcMap,grassmask)
tcgrass.df<-as.data.frame(getValues(tcgrass))
tccrop<-crop(tcMap,cropmask)
tccrop.df<-as.data.frame(getValues(tccrop))
Compute RMSE for each class
RMSE(gwt.df,tcfor.df)
## [1] 31.74691
RMSE(gwt.df,tcgrass.df)
## [1] 31.74691
RMSE(gwt.df,tccrop.df)
## [1] 31.74691