knitr::opts_chunk$set(echo = TRUE, fig.width=7) library(tidyverse) library(stringr) # library(forcats) # library(sp) #for maps # library(tmap) #for maps library(knitr) #for tables with kable library(climcropr) library(raster) library(rnaturalearth) #for maps library(tmap) # for maps library(dismo) #for ecocrop # extent object for use in plots ext <- extent(-180,180,-60,80)
Draft paper. Journal options :
We describe a simple, generic, mechanistic approach for investigating the broad responses to climate change of the global distributions of hundreds of crops.
We use temperature and rainfall requirements stored in the FAO ecocrop database to assess crop suitability by comparison with predicted monthly climate data. Our method is based on, and simpler than, existing Ecocrop modelling approaches.
Our method predicts if an area is suitable or not (0/1), rather than predicting a suitability value between 0 and 1
We apply this simpler method to X crops at a global scale and test results against MIRCA harvested area data for the year 2000.
This new simpler method produces better true positive rates than the original ecocrop model when tested against the MIRCA data.
Existing ecocrop models have not been applied to a large number of crops at large geographic extents even though the potential to do this is one of the advantages of its simplicity.
This new approach is both simpler and more transparent. We provide a documented R package implementing the method, including methods to test against field data.
~ end of abstract
[@Ramirez-Villegas2013] sorghum paper [@Anderson2015] differences in global crop models and maps [@Hijmans2012] diva-gis manual [@Hijmans2017] dismo R package [@Estes2013] comparing mechanistic and empirical crop models [@Holzkamper2015] climate change impacts on maize based on 3 different modelling approaches [@Iizumi2015] how do weather influence croppping area and intensity [@Leff2004] geographic distribution of major crops [@Mueller2017] global gridded crop model evaluation [@Porter2014] IPCC AR5 agriculture chapter [@Portmann2010] MIRCA crop maps
Changes in temperature and rainfall predicted in high-end climate scenarios are outside of the tolerances of many existing crops in many of the areas where they are currently grown ?[@Porter2014]. Potential adaptation strategies include growing crops in new areas that become suitable under a changed climate and stopping growing certain crops in areas that become unsuitable. Global assessments of likely impacts on crops and the potential for these adaptation strategies would be aided by an ability to predict suitability of areas for a wide range of crops at the global scale.
There are a wide range of existing approaches for predicting the response of crop distributions to climate change [?refs]. These differ in whether they are statistical or mechanistic and in the level of detail they include. There is a trade off between this level of detail and the generality of application in terms of numbers of crops and geographic area. Detailed models, e.g. representing the growth of crops daily, have data requirements that restrict their application to very few crops and to restricted geographic areas.
A relatively simple mechanistic approach based upon the temperature and precipitation requirements of hundreds of crops held in the FAO EcoCrop database was developed more than 15 years ago. This modeling approach, also termed EcoCrop, was implemented in both GIS and a package in the statistical language R. A more recent paper describes the application of a modified version of this approach to a single crop, Sorghum[@Ramirez-Villegas2013].
The FAO ecocrop database holds data for more than 2500 crops including requirements for temperature, rainfall and soils based upon expert knowledge. The ecocrop modelling approach estimates suitability for crops based on temperature and precipitation using these requirements[@Ramirez-Villegas2013]. The ecocrop modelling approach has been implemented in a number of slightly different ways and can be run from an R package[@Hijmans2017] and Diva-GIS[@Hijmans2012]. Ecocrop the model is designed to be simpler than other crop models allowing it to be applied to a wider range of crops and situations.
In summary the ecocrop the modelling approach : 1. Calculates a mean of the minimum and maximum crop growth cycle 2. Rounds this mean (up or down) to the nearest number of months to calculate a 'duration' 3. Finds whether there are 'duration' consecutive months in between the ecocrop temperature limits 4. Finds whether there is a concurrent 'duration' period where the total precipitation is between the ecocrop rainfall requirements of the crop.
This is a summary of the ecocrop model as implemented within the R package dismo and within Diva-GIS.
The original ecocrop model uses 'optimal' temperature and precipitation limits specified in FAO ecocrop to develop an index of suitability per month, the best month and the value of the index in the best month.
Ecocrop the model as implemented in this way has not been well tested against empirical data.
The existing ecocrop modelling approach involves a number of steps that are not entirely straightforward and, we would argue, are not well justified.
Firstly a mean of the minimum and maximum crop growth cycles is used as one of the most influential parameters. For example for maize the minimum and maximum crop growth cycles are 65 days and 365 days which round to 3 months and 12 months. The ecocrop model thus assesses temperatures for a 7 month growth cycle. The figure below shows the minimum and maximum crop growth cycles stored within ecocrop for some important crops.
Secondly the crop parameters as specified in the FAO ecocrop database are necessarily very broad. Whilst they are based on expert judgement they cannot hope to capture the majority of the processes that influence the suitability of an area for a crop. For this reason a more realistic goal than trying to predict a suitability score is to try to predict which areas are definitely not suitable for a crop. This also has the advantage that predicted absence is easier than a suitability score to test against global crop data.
We aim to move towards a simpler more straightforward method.
The proposed method is :
The base ecocrop predictions have some aspects that also look wrong for example they too predict that maize will not grow in Europe, the ecocrop method of using the mean growing cycle to find time periods without low temperatures excludes moderately northern latitudes.
TODO ~ I need to justify advantages over a statistical approach (statistical works on where crops are grown not on where they could be grown)
Cut from above : It aims for a conservative approach, to be able to exclude areas that are unsuitable with some confidence, while being less concerned that some unsuitable areas are classed as suitable. [todo I'm not sure about that sentence]
# new simpler method for predicting suitability #cropnames <- c('maize','wheat','rice','potato','soya bean','sugarcane') #beware underscore in soya_bean cropnames <- c('maize','rice','wheat','soya_bean') #using cr_suit_simpler #dataframe to store results to output a table dfres <- data.frame( crop=cropnames, simple_true_positive=NA, ecocrop_true_positive=NA) # dfres <- data.frame( crop=cropnames, # simple_true_positive=NA, # ecocrop_true_positive=NA, # simple_true_negative=NA, # ecocrop_true_negative=NA) cropnum <- 0 for( crop in cropnames) { cropnum <- cropnum +1 # this uses st, a raster stack stored in the package containing crop predictions & mirca data obs <- subset(st,paste0(crop,'_mirca')) #compare suitsimp to Mirca pred <- subset(st,paste0(crop,'_suitsimp')) tpos_s <- true_pos(obs,pred) dfres$simple_true_positive[cropnum] <- signif(tpos_s,2) #dfres$simple_true_negative[cropnum] <- signif(true_neg(obs,pred),2) #compare ecocrop to Mirca pred <- subset(st,paste0(crop,'_ecocrop')) tpos_e <- true_pos(obs,pred) dfres$ecocrop_true_positive[cropnum] <- signif(tpos_e,2) #dfres$ecocrop_true_negative[cropnum] <- signif(true_neg(obs,pred),2) #cat(paste(crop, 'simp:', tpos_s, 'ecocrop:', tpos_e, '\n\n' )) } kable(dfres)
# testing tmax method against simpsuit and ecocrop # based on files held in memory and saved as Rds # so eval=FALSE for now st_tmax <- readRDS('C:\\Dropbox\\ueaHelix2017\\ecocrop\\andy_code\\st_tmax.Rds') #cropnames <- c('maize','wheat','rice','potato','soya bean','sugarcane') #beware underscore in soya_bean cropnames <- c('maize','rice','wheat','soya_bean','sorghum') #dataframe to store results to output a table dfres <- data.frame( crop=cropnames, simple_true_positive=NA, tmax_true_positive=NA, ecocrop_true_positive=NA) cropnum <- 0 for( crop in cropnames) { cropnum <- cropnum +1 # this uses st, a raster stack stored in the package containing crop predictions & mirca data obs <- subset(st,paste0(crop,'_mirca')) #tpos suitsimp to Mirca pred <- subset(st,paste0(crop,'_suitsimp')) tpos_s <- true_pos(obs,pred) dfres$simple_true_positive[cropnum] <- signif(tpos_s,2) #tpos tmax to Mirca #currently stored in different place pred <- subset(st_tmax,paste0(crop,'_tmax')) tpos_s <- true_pos(obs,pred) dfres$tmax_true_positive[cropnum] <- signif(tpos_s,2) #tpos ecocrop to Mirca pred <- subset(st,paste0(crop,'_ecocrop')) tpos_e <- true_pos(obs,pred) dfres$ecocrop_true_positive[cropnum] <- signif(tpos_e,2) #dfres$ecocrop_true_negative[cropnum] <- signif(true_neg(obs,pred),2) #cat(paste(crop, 'simp:', tpos_s, 'ecocrop:', tpos_e, '\n\n' )) } kable(dfres)
# new simpler method for predicting suitability #cropnames <- c('maize','wheat','rice','potato','soya bean','sugarcane') #beware underscore in soya_bean cropnames <- c('maize','rice','wheat','soya_bean') #using cr_suit_simpler #dataframe to store results to output a table dfres <- data.frame( crop=cropnames, simple_true_negative=NA, ecocrop_true_negative=NA) cropnum <- 0 for( crop in cropnames) { cropnum <- cropnum +1 # this uses st, a raster stack stored in the package containing crop predictions & mirca data obs <- subset(st,paste0(crop,'_mirca')) #tneg suitsimp to Mirca pred <- subset(st,paste0(crop,'_suitsimp')) dfres$simple_true_negative[cropnum] <- signif(true_neg(obs,pred),2) #tneg ecocrop to Mirca pred <- subset(st,paste0(crop,'_ecocrop')) dfres$ecocrop_true_negative[cropnum] <- signif(true_neg(obs,pred),2) } kable(dfres)
Both Mirca and ecocrop have a gradation of values, these are converted to 0/1 in the testing process.
In the first set of maps I convert everything to 0/1 to aid comparisons.
In the 2nd set of maps I keep the range of values in the Mirca and ecocrop predictions. In these later maps grey in the Mirca maps represents harvested area greater than 0 (but low). Grey in the suitability maps represents 0 suitability. I think that the fact that the green pattern in the suitability maps follows the grey pattern in the mirca maps is a good sign. I just want us to discuss this and then I can improve the colour schemes.
\pagebreak
#fig.height reduced to try to get 3 plots on a page #beware underscore in soya_bean cropnames <- c('maize','rice','wheat','soya_bean') #this doesn't currently help with plotting maps & chops off some of predictions #bbox <- raster::extent(-180,180,-40,75) bbox <- raster::extent(-180,180,-50,80) cropnum <- 0 for( crop in cropnames) { cropnum <- cropnum +1 # the mirca data has zeroes in the ocean # I can replace 0 with NA for plotting # this might influence the false negative testing # mirca rst <- raster::subset(st,paste0(crop,'_mirca')) # for 0/1 plots rst[rst >0] <- 1 rst[rst==0] <- NA par(mar=c(0,0,2,0)) #bltr plot(rst, main=paste0(crop,' Mirca 0/1'), ext=bbox, legend=FALSE) plot(ne_countries(), add=TRUE, border='grey', lwd=0.1) # simple suit rst <- raster::subset(st,paste0(crop,'_suitsimp')) # for 0/1 plots rst[rst >0] <- 1 rst[rst==0] <- NA par(mar=c(0,0,2,0)) #bltr plot(rst, main=paste0(crop,' simple suit'), ext=bbox, legend=FALSE) plot(ne_countries(), add=TRUE, border='grey', lwd=0.1) # ecocrop rst <- raster::subset(st,paste0(crop,'_ecocrop')) # for 0/1 plots rst[rst >0] <- 1 rst[rst==0] <- NA par(mar=c(0,0,2,0)) #bltr plot(rst, main=paste0(crop,' ecocrop 0/1'), ext=bbox, legend=FALSE) plot(ne_countries(), add=TRUE, border='grey', lwd=0.1) }
The new simpler method is quantitatively better than ecocrop when compared to Mirca, but still has large differences from Mirca.
#fig.height reduced to try to get 3 plots on a page #beware underscore in soya_bean cropnames <- c('maize','rice','wheat','soya_bean') #this doesn't currently help with plotting maps & chops off some of predictions #bbox <- raster::extent(-180,180,-40,75) bbox <- raster::extent(-180,180,-50,80) cropnum <- 0 for( crop in cropnames) { cropnum <- cropnum +1 # the mirca data has zeroes in the ocean # I can replace 0 with NA for plotting # this might influence the false negative testing # mirca rst_mirca <- raster::subset(st,paste0(crop,'_mirca')) # for 0/1 plots but beware of effect on calculations rst_mirca[rst_mirca >0] <- 1 # simple suit rst_base <- raster::subset(st,paste0(crop,'_suitsimp')) rst_change <- rst_base - rst_mirca tm <- tm_shape(rst_change) + tm_raster(style='cat', palette = c('red4','grey95','green4'), labels = c('mirca only','same','baseline only'), title = 'suitability change') + tm_shape(ne_countries()) + tm_borders(col='grey') + tm_layout(legend.position = c("left","bottom"), main.title=paste0(crop,' baseline - mirca'), main.title.size=1) print(tm) }
The utility of having simple 0/1 predictions is that it is also clearer to compare predicted change against a baseline. Calculating future - baseline gives you +1 for areas expected to gain the ability to support a crop and -1 for areas expected to lose the ability to support a crop. These can be displayed as in the map below.
maize_change <- maize_future - subset(st,"maize_suitsimp") #plot(maize_change) library(tmap) tm_shape(maize_change) + tm_raster(style='cat', palette = c('red4','grey95','green4'), labels = c('loss','same','gain'), title = 'suitability change') + tm_shape(ne_countries()) + tm_borders(col='black') + tm_layout(legend.position = c("left","bottom"))
sorghum_tmax <- ecocrop_a_raster('broom-corn',st_clim, simpler=TRUE, use_tmax=TRUE) #test this against both tavg and Mirca crop <- 'sorghum' sorghum_tavg <- raster::subset(st,paste0(crop,'_suitsimp')) sorghum_mir <- raster::subset(st,paste0(crop,'_mirca')) # this showed no difference at current temperatures plot(sorghum_tmax-sorghum_tavg) summary(sorghum_tmax-sorghum_tavg) # but sorghum max is 40 degrees and min growth cycle is 3 months # as Jeff said rainfall probably already excludes any areas that have >40 degrees for 3 months # potato max is 30 degrees, does it have a difference ? potato_tmax <- ecocrop_a_raster('potato',st_clim, simpler=TRUE, use_tmax=TRUE) crop <- 'potato' potato_tavg <- ecocrop_a_raster('potato',st_clim, simpler=TRUE, use_tmax=FALSE) #potato_mir <- raster::subset(st,paste0(crop,'_mirca')) #aha good ! plot(potato_tavg-potato_tmax) #compare to Mirca folder <- 'C:\\Dropbox\\ueaHelix2017\\MIRCA\\_half_degree\\' potato_mirca <- raster(SDMTools::read.asc.gz(paste0(folder,'annual_area_harvested_rfc_crop10_ha_30mn.asc.gz'))) #Jeff said tmax looking better, even though it does decrease the truepos rate #but said for a paper I would then need to defend not using #tmin rather than tavg for min temps #BUT is tmax better than base ecocrop for our 4 crops ? true_pos(potato_mirca,potato_tmax) #[1] 0.6304388 true_pos(potato_mirca,potato_tavg) #[1] 0.7948575 true_neg(potato_mirca,potato_tmax) #[1] 0.1350915 true_neg(potato_mirca,potato_tavg) #[1] 0.1129034 plot(potato_mirca>0) plot((potato_mirca>0)-potato_tmax) plot(potato_tmax) plot(potato_mirca>0))
# eval=FALSE for now # Plotting maps with gradations of predictions and Mirca # fig.height reduced to try to get 3 plots on a page #beware underscore in soya_bean cropnames <- c('maize','rice','wheat','soya_bean') #this doesn't currently help with plotting maps & chops off some of predictions #bbox <- raster::extent(-180,180,-40,75) bbox <- raster::extent(-180,180,-50,80) cropnum <- 0 for( crop in cropnames) { cropnum <- cropnum +1 # the mirca data has zeroes in the ocean # I can replace 0 with NA for plotting # this might influence the false negative testing # mirca rst <- raster::subset(st,paste0(crop,'_mirca')) rst[rst==0] <- NA par(mar=c(0,0,2,0)) #bltr plot(rst, main=paste0(crop,' Mirca'), ext=bbox) plot(ne_countries(), add=TRUE, border='grey', lwd=0.1) # simple suit rst <- raster::subset(st,paste0(crop,'_suitsimp')) par(mar=c(0,0,2,0)) #bltr plot(rst, main=paste0(crop,' simple suit'), ext=bbox) plot(ne_countries(), add=TRUE, border='grey', lwd=0.1) # ecocrop rst <- raster::subset(st,paste0(crop,'_ecocrop')) par(mar=c(0,0,2,0)) #bltr plot(rst, main=paste0(crop,' ecocrop'), ext=bbox) plot(ne_countries(), add=TRUE, border='grey', lwd=0.1) }
# plot crop cycle min and max cropnames <- c('maize','wheat','rice','potato','soya bean','sugarcane') cr_plot_cycle(cropnames)
temporary citations to start ref list [@Ramirez-Villegas2013] sorghum paper [@Anderson2015] differences in global crop models and maps [@Hijmans2012] diva-gis manual [@Estes2013] comparing mechanistic and empirical crop models [@Holzkamper2015a] climate change impacts on maize based on 3 different modelling approaches [@Iizumi2015a] how do weather influence croppping area and intensity [@Leff2004a] geographic distribution of major crops [@Muller2017a] global gridded crop model evaluation [@Portmann2010a] MIRCA crop maps
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.