Title: | Quantitative Evaluation of the Native Fertility of Tropical Soils |
---|---|
Description: | An implementation of the QUEFTS (Quantitative Evaluation of the Native Fertility of Tropical Soils) model. The model (1) estimates native nutrient (N, P, K) supply of soils from a few soil chemical properties; and (2) computes crop yield given that supply, crop parameters, fertilizer application, and crop attainable yield. See Janssen et al. (1990) <doi:10.1016/0016-7061(90)90021-Z> for the technical details and Sattari et al. (2014) <doi:10.1016/j.fcr.2013.12.005> for a recent evaluation and improvements. |
Authors: | Robert J. Hijmans [cre, aut], Pieter Pypers [ctb, aut], Joost Wolff [ctb] |
Maintainer: | Robert J. Hijmans <[email protected]> |
License: | GPL (>=3) |
Version: | 1.2-3 |
Built: | 2024-11-02 03:41:59 UTC |
Source: | https://github.com/cropmodels/Rquefts |
This package provides implments the QUEFTS model.
QUEFTS (Quantitative Evaluation of the Native Fertility of Tropical Soils) model (1) estimates native nutrient (N, P, K) supply of soils from a few soil chemical properties; and (2) computes crop yield given that supply, fertilizer application and crop parameters. See Janssen et al. (1990) <doi:10.1016/0016-7061(90)90021-Z> for the technical details and Sattari et al. (2014) <doi:10.1016/j.fcr.2013.12.005> for a recent evaluation and improvements.
The package is particularly useful if you want to make spatial predictions with QUEFTS.
There are also a few functions that can help with computing the amount of nutriets supplied with fertilizer (blends) and compute the optimal use of fertilizer given a goal in nutrients, available products, and their prices.
Make many predictions with a QUEFTS model.
## S4 method for signature 'Rcpp_QueftsModel' batch(x, supply, fert, yatt, leaf_ratio, stem_ratio, var="yield")
## S4 method for signature 'Rcpp_QueftsModel' batch(x, supply, fert, yatt, leaf_ratio, stem_ratio, var="yield")
x |
QUEFTSModel |
supply |
matrix or data.frame with soil nutrient supply data for N, P, and K |
fert |
matrix or data.frame with fertilizer nutrient supply data for N, P, and K |
yatt |
numeric. Attainable yield |
leaf_ratio |
positive numeric (typically between 0 and 1) indicating the leaf weight relative to the storage organ weight. For example: 0.46 for maize, 0.17 for potato, and 0.18 for rice |
stem_ratio |
positive numeric (typically between 0 and 1) indicating the stem weight relative to the storage organ weight, For example: 0.56 for maize, 0.14 for potato, and 0.67 for rice |
var |
character. Output variable name. Either "yield" or "gap" |
numeric or matrix (if var="gap"
)
potato <- quefts_crop("potato") q <- quefts(crop=potato) fert=cbind(c(0,100), c(0,200), c(0,30)) supply=cbind(50,50,25) yatt <- 10000 batch(q, supply, fert, yatt, 0.45, 0.4) batch(q, supply, fert, yatt, 0.45, 0.4, var="gap")
potato <- quefts_crop("potato") q <- quefts(crop=potato) fert=cbind(c(0,100), c(0,200), c(0,30)) supply=cbind(50,50,25) yatt <- 10000 batch(q, supply, fert, yatt, 0.45, 0.4) batch(q, supply, fert, yatt, 0.45, 0.4, var="gap")
Compute the optimal fertilizer application rates given a target nutrient application and the available products (fertilizer blends) and their prices.
fertApp(nutrients, fertilizers, price, exact=TRUE, retCost=FALSE)
fertApp(nutrients, fertilizers, price, exact=TRUE, retCost=FALSE)
nutrients |
data.frame with columns "N", "P", "K" in kg (per unit area) |
fertilizers |
data.frame with fertilizer products (see examples) |
price |
numeric. Vector with fertilizer product prices. Should have length of |
exact |
logical. If |
retCost |
logical. If |
# fertilizer product list fert <- fertilizers() # shortening some of the names for display fert[,2] = substr(fert[,2], 1, 20) # contents are expressed as a percentage. ferts <- fert[c(8,15:17), 2:5] ferts x <- fertApp(data.frame(N=100, P=50, K=50), ferts, c(1, 1.5, 1.25, 1)) # show that it is correct nutrientRates(ferts, x[,2]) fertApp(data.frame(N=seq(0,200,50), P=50, K=50), ferts, c(1, 1.5, 1.25, 0.75)) fertApp(data.frame(N=seq(0,200,50), P=50), ferts[,-3], c(1, 1.5, 1.25, 0.75)) fertApp(data.frame(N=seq(0,200,50), P=50), ferts[,-3], c(1, 1.5, 1.25, 5.75))
# fertilizer product list fert <- fertilizers() # shortening some of the names for display fert[,2] = substr(fert[,2], 1, 20) # contents are expressed as a percentage. ferts <- fert[c(8,15:17), 2:5] ferts x <- fertApp(data.frame(N=100, P=50, K=50), ferts, c(1, 1.5, 1.25, 1)) # show that it is correct nutrientRates(ferts, x[,2]) fertApp(data.frame(N=seq(0,200,50), P=50, K=50), ferts, c(1, 1.5, 1.25, 0.75)) fertApp(data.frame(N=seq(0,200,50), P=50), ferts[,-3], c(1, 1.5, 1.25, 0.75)) fertApp(data.frame(N=seq(0,200,50), P=50), ferts[,-3], c(1, 1.5, 1.25, 5.75))
Computes the amount of nutrients given a rate of fertilizer.
fertilizers() nutrientRates(supply, treatment)
fertilizers() nutrientRates(supply, treatment)
supply |
data.frame with columns "N", "P", "K" expressed as percentage of the product (row) |
treatment |
amounts applied |
# fertilizer product list fert <- fertilizers() # shortening some of the names for display fert[,2] = substr(fert[,2], 1, 20) # contents are expressed as a percentage. fert myferts <- fert[c(8,15), ] nutrientRates(myferts, c(100,50))
# fertilizer product list fert <- fertilizers() # shortening some of the names for display fert[,2] = substr(fert[,2], 1, 20) # contents are expressed as a percentage. fert myferts <- fert[c(8,15), ] nutrientRates(myferts, c(100,50))
nutSupply1
computes the base (unfertilized) soil supply of N, P and K according to Janssen et al. (1990), Table 2. For use with the QUEFTS model.
nutSupply2
is a modified version following Sattari et al. (2014). It has an additional variable "temperature", and P-total is required. Sattari et al suggest that, for soils that have not been fertilized with P, you can estimate P-total as 95 * P-Olsen
. Using AfSIS data I found 55 * P-Olsen
.
nutSupply1(pH, SOC, Kex, Polsen, Ptotal=NA) nutSupply2(temp, pH, SOC, Kex, Polsen, Ptotal)
nutSupply1(pH, SOC, Kex, Polsen, Ptotal=NA) nutSupply2(temp, pH, SOC, Kex, Polsen, Ptotal)
temp |
average growing season temperature (C) |
pH |
soil pH (H2O) |
SOC |
soil organic carbon (g/kg) |
Kex |
exchangeable K in the soil (mmol/kg) |
Polsen |
soil P measured with the P-Olsen method (mg/kg) |
Ptotal |
total soil P (mg/kg) |
Matrix with three columns: Nsup, Psup and Ksup. These are the potential supply of N, P and K of the unfertilized soil (kg/ha).
Janssen B.H., F.C.T. Guiking, D. van der Eijk, E.M.A. Smaling, J. Wolf and H. van Reuler, 1990. A system for the quantitative evaluation of the fertility of tropical soils (QUEFTS). Geoderma 46: 299-318
Sattari, S.Z., M.K. van Ittersum, A.F. Bouwman, A.L. Smit, and B.H. Janssen, 2014. Crop yield response to soil fertility and N, P, K inputs in different environments: Testing and improving the QUEFTS model. Field Crops Research 157: 35-46
s1 <- nutSupply1(6, c(23, 11, 35), 15, c(1.6, 2.6, 2.4)) s1 s2 <- nutSupply2(20, 6, c(23, 11, 35), 15, c(1.6, 2.6, 2.4), 225) s2
s1 <- nutSupply1(6, c(23, 11, 35), 15, c(1.6, 2.6, 2.4)) s1 s2 <- nutSupply2(20, 6, c(23, 11, 35), 15, c(1.6, 2.6, 2.4), 225) s2
Make spatial predictions with a QUEFTS model. First create a model, then use the model with a SpatRaster of soil properties to make spatial predictions.
## S4 method for signature 'Rcpp_QueftsModel' predict(object, supply, yatt, leaf_ratio, stem_ratio, var="yield", filename="", overwrite=FALSE, ...)
## S4 method for signature 'Rcpp_QueftsModel' predict(object, supply, yatt, leaf_ratio, stem_ratio, var="yield", filename="", overwrite=FALSE, ...)
object |
QUEFTSModel |
supply |
SpatRaster with nutrient supply data (Ns, Ps, Ks) |
yatt |
SpatRaster with attainable yield |
leaf_ratio |
positive numeric (typically between 0 and 1) indicating the leaf weight relative to the storage organ weight. For example: 0.46 for maize, 0.17 for potato, and 0.18 for rice |
stem_ratio |
positive numeric (typically between 0 and 1) indicating the stem weight relative to the storage organ weight, For example: 0.56 for maize, 0.14 for potato, and 0.67 for rice |
var |
character. Output variable name. Either "yield" or "gap" |
filename |
character. Output filename. Optional |
overwrite |
logical. If |
... |
list. Options for writing files as in |
SpatRaster
library(terra) ff <- list.files(system.file("sp", package="Rquefts"), full.names=TRUE) r <- rast(ff) soil <- r[[c("Tavg", "pH", "SOC", "Kex", "Pex", "Ptot")]] supply <- lapp(soil, nutSupply2) plot(supply) yatt <- rast(system.file("sp/Ya.tif", package="Rquefts")) maize <- quefts_crop("Maize") fertilizer <- list(N=0, P=0, K=0) q <- quefts(crop=maize, fert=fertilizer) p <- predict(q, supply, yatt, 0.46, 0.56) plot(p) g <- predict(q, supply, yatt, 0.46, 0.56, "gap") plot(g)
library(terra) ff <- list.files(system.file("sp", package="Rquefts"), full.names=TRUE) r <- rast(ff) soil <- r[[c("Tavg", "pH", "SOC", "Kex", "Pex", "Ptot")]] supply <- lapp(soil, nutSupply2) plot(supply) yatt <- rast(system.file("sp/Ya.tif", package="Rquefts")) maize <- quefts_crop("Maize") fertilizer <- list(N=0, P=0, K=0) q <- quefts(crop=maize, fert=fertilizer) p <- predict(q, supply, yatt, 0.46, 0.56) plot(p) g <- predict(q, supply, yatt, 0.46, 0.56, "gap") plot(g)
Create a QUEFTS model, set parameters, and run it to compute nutrient requirements and nutrient limited yield.
A number of default crop parameter sets are available from quefts_crop
, and an example soil from quefts_soil
. You need to provide attainable or target crop production (in this context that is the maximum production in the absence of nutrient limitation), expressed as dry-matter biomass for leaves, stems and the storage organ (e.g. grain, root or tuber). See quefts_biom
. Some crops are grown for the stems/leaves, in which case there is no relevant storage organ (e.g. sugarcane, jute). production yield estimates can be obtained with a crop growth model.
quefts(soil, crop, fert, biom) quefts_fert() quefts_biom() crop(x) <- value soil(x) <- value fert(x) <- value biom(x) <- value run(x, ...)
quefts(soil, crop, fert, biom) quefts_fert() quefts_biom() crop(x) <- value soil(x) <- value fert(x) <- value biom(x) <- value run(x, ...)
soil |
list with named soil parameters. See Details. An example is returned by |
crop |
list with named crop parameters. See Details. An example is returned by |
fert |
list with named fertilizer parameters (N, P and K). An example is returned by |
biom |
list with named biomass and growing season length parameters. An example is returned by |
x |
QueftsModel object |
value |
list with soil, crop, fertilizer, or biomass parameters as above |
... |
additional arguments. None implemented |
For input parameters see quefts_crop
, quefts_soil
, quefts_fert
and quefts_biom
Crop yield (biom) | . | |
leaf_att, stem_att, store_att |
Attainable (in the absence of nutrient limitation), or target crop biomass (dry-matter, kg/ha) for leaves, stems and storage organs. | |
SeasonLength |
Length of the growing season (days) | |
. | ||
. | ||
Output Variables | Explanation | |
N_actual_supply, P_actual_supply, K_actual_supply |
nutrient uptake from soil (not fertilizer) (kg/ha) | |
leaf_lim, stem_lim, store_lim |
nutrient limited biomass of leaves, stems, and storage organ (kg/ha) | |
N_gap, P_gap, K_gap |
fertilizer required to reach the specified biomass (kg/ha) | |
vector with output variables as described in the Details
Janssen B.H., F.C.T. Guiking, D. van der Eijk, E.M.A. Smaling, J. Wolf and H. van Reuler, 1990. A system for the quantitative evaluation of the fertility of tropical soils (QUEFTS). Geoderma 46: 299-318
Sattari, S.Z., M.K. van Ittersum, A.F. Bouwman, A.L. Smit, and B.H. Janssen, 2014. Crop yield response to soil fertility and N, P, K inputs in different environments: Testing and improving the QUEFTS model. Field Crops Research 157: 35-46
# create a QUEFTS model # 1. get parameters soiltype <- quefts_soil() barley <- quefts_crop("Barley") fertilizer <- list(N=0, P=0, K=0) att_yield <- list(leaf_att=2200, stem_att=2700, store_att=4800, SeasonLength=110) # 2. create a model q <- quefts(soiltype, barley, fertilizer, att_yield) # 3. run the model run(q) # change some parameters q$SeasonLength <- 162 q$leaf_att <- 2651 q$stem_att <- 5053 q$store_att <- 8208 q$N <- 100 q$P <- 50 q$K <- 50 run(q) ## note that Rquefts uses C++ reference classes. ## This means that if you copy a quefts model, you do not create a ## new instance of the model, but you point to the same one! q <- quefts() q["N"] k <- q k["N"] <- 150 k["N"] # the value of q has also changed! q["N"] ## different ways of subsetting / replacement q <- quefts() q$N q$N <- 30 q["N"] q["N"] <- 90 q["model", "N"] q["model", "N"] <- 60 q$N q$soil$N_recovery q["soil$N_recovery"] q["soil$N_recovery"] <- .6 q["soil", "N_recovery"] q["soil", "N_recovery"] <- .4 q$soil$N_recovery
# create a QUEFTS model # 1. get parameters soiltype <- quefts_soil() barley <- quefts_crop("Barley") fertilizer <- list(N=0, P=0, K=0) att_yield <- list(leaf_att=2200, stem_att=2700, store_att=4800, SeasonLength=110) # 2. create a model q <- quefts(soiltype, barley, fertilizer, att_yield) # 3. run the model run(q) # change some parameters q$SeasonLength <- 162 q$leaf_att <- 2651 q$stem_att <- 5053 q$store_att <- 8208 q$N <- 100 q$P <- 50 q$K <- 50 run(q) ## note that Rquefts uses C++ reference classes. ## This means that if you copy a quefts model, you do not create a ## new instance of the model, but you point to the same one! q <- quefts() q["N"] k <- q k["N"] <- 150 k["N"] # the value of q has also changed! q["N"] ## different ways of subsetting / replacement q <- quefts() q$N q$N <- 30 q["N"] q["N"] <- 90 q["model", "N"] q["model", "N"] <- 60 q$N q$soil$N_recovery q["soil$N_recovery"] q["soil$N_recovery"] <- .6 q["soil", "N_recovery"] q["soil", "N_recovery"] <- .4 q$soil$N_recovery
Crop biomass parameters
For a cereal crop you can generally assume that about 50% of the total biomass is grain, and about 30% is stem and 20% is leaf biomass.
quefts_biom()
quefts_biom()
Crop yield (biom) | . | |
leaf_att, stem_att, store_att |
Attainable (in the absence of nutrient limitation), or target crop biomass (dry-matter, kg/ha) for leaves, stems and storage organs. | |
SeasonLength |
Length of the growing season (days) | |
list
b <- quefts_biom() str(b)
b <- quefts_biom() str(b)
A number of default crop parameter sets are provided
quefts_crop(name="")
quefts_crop(name="")
name |
character. crop name |
Input Parameters | Explanation | |
_minVeg, _maxVeg, _minStore, _maxStore |
minimum and maximum concentration of "_ " (N, P, or K) in vegetative organs and in storage organs (kg/kg) |
|
Yzero |
the maximum biomass of vegetative organs at zero yield of storage organs (kg/ha) | |
Nfix |
the fraction of a crop's nitrogen uptake supplied by biological fixation | |
list with crop parameters. See Details
barley <- quefts_crop("Barley") str(barley)
barley <- quefts_crop("Barley") str(barley)
Get a list with the default fertilization parameters
quefts_fert()
quefts_fert()
Input Parameters | Explanation | |
Management (fert) | . | |
N, P, K |
N, P, and K fertilizer applied. | |
list
f <- quefts_fert() str(f)
f <- quefts_fert() str(f)
Example soil parameters.
quefts_soil()
quefts_soil()
Input Parameters | Explanation | |
N_base_supply, P_base_supply, K_base_supply |
Potential supply (kg/ha) of N, P and K of the (unfertilized) soil in a growing season of standard length (default is 120 days). See nutSupply2 to estimate that. |
|
N_recovery, P_recovery, K_recovery |
Fertilizer recovery, that is, the fraction of applied fertilizer that can be taken up by the plant. | |
UptakeAdjust |
Two-column matrix to compute the fraction uptake from soil supply as function of length of season. The default standard season length is 120 days. The first column is the length of the growing season, the second column is the fraction uptake. Intermediate values are computed by linear interpolation. | |
list with soil parameters
soiltype <- quefts_soil() str(soiltype)
soiltype <- quefts_soil() str(soiltype)
Estimate the apparent base (unfertilized) soil supply of N, P and K based on nutrient omission trial data and a "reverse" QUEFTS approach. The apparent supply is found with optimization.
revSupply(obs, crop, soil, Ya, leaf_ratio, stem_ratio, SeasonLength = 120, ...)
revSupply(obs, crop, soil, Ya, leaf_ratio, stem_ratio, SeasonLength = 120, ...)
obs |
data.frame with observed data from a nutrient omission trial. It must have these four columns: "N", "P", "K" and "Y"; that give the N, P, and K fertilizer application and the crop yield in kg/ha |
Ya |
numeric. Attainable yield |
soil |
list with named soil parameters. See |
crop |
list with named crop parameters. See |
leaf_ratio |
positive numeric (typically between 0 and 1) indicating the leaf weight relative to the storage organ weight. For example: 0.46 for maize, 0.17 for potato, and 0.18 for rice |
stem_ratio |
positive numeric (typically between 0 and 1) indicating the stem weight relative to the storage organ weight, For example: 0.56 for maize, 0.14 for potato, and 0.67 for rice |
SeasonLength |
positive integer |
... |
additional arguments supplied to |
numeric vector with the N, P, and K supply in kg/ha
?
set.seed(777) trial_data <- data.frame(treat = c("CON", "NPK", "NPK", "PK", "NK", "NP"), N = c(0, 120, 120, 0, 120, 120), P = c(0, 30, 30, 30, 0, 30), K = c(0, 60, 60, 60, 60, 0), Y = c(2000, 6000, 6000, 2500, 4500, 5500) + rnorm(6, 0, 500)) Ya <- max(trial_data$Y) + 1000 crop <- quefts_crop("Potato") soil <- quefts_soil() revSupply(trial_data, crop, soil, Ya, leaf_ratio=.17, stem_ratio=.14)
set.seed(777) trial_data <- data.frame(treat = c("CON", "NPK", "NPK", "PK", "NK", "NP"), N = c(0, 120, 120, 0, 120, 120), P = c(0, 30, 30, 30, 0, 30), K = c(0, 60, 60, 60, 60, 0), Y = c(2000, 6000, 6000, 2500, 4500, 5500) + rnorm(6, 0, 500)) Ya <- max(trial_data$Y) + 1000 crop <- quefts_crop("Potato") soil <- quefts_soil() revSupply(trial_data, crop, soil, Ya, leaf_ratio=.17, stem_ratio=.14)