sbegueria / spei Goto Github PK
View Code? Open in Web Editor NEWAn R package for computing the Standardized Precipitation-Evapotranspiration Index (SPEI), Penman-Monteith and other reference evapotranspiration, SPI, etc.
An R package for computing the Standardized Precipitation-Evapotranspiration Index (SPEI), Penman-Monteith and other reference evapotranspiration, SPI, etc.
Has anyone found a solution to this problem of infinite SPEI values? I calculate the global SPEI using CESM-LE data and get an infinite value (-Inf or -Inf). I already consider na.rm =TRUE even though I have no missing value in my data.
Should I replace -Inf with -3 and Inf with 3, does this make sense?
I have already calculated SPEI ( PET with THornthwaite, Hargreave and Penman) taking different distributions such as Logistic, Gamma, PearsonIII, but I still have these values Infinite and NaN.
Any help and advice is welcome
We are currently using the SPEI package for calculating drought indicators in our project. While doing so, we realised a slight difference in the implementation of thornthwaite PET specifically how declination angle is used.
In Vicente-Serrano et. al. (2010), the equations are given as
which is then used in computing hourly angle of sun rising
However, when looking at the implementation in thornthwaite.R, we noticed
tanDelta <- c(-0.37012566,-0.23853358,-0.04679872,0.16321764, 0.32930908,0.40677729,0.3747741,0.239063,
0.04044485,-0.16905776,-0.33306377,-0.40743608)
which is a vector of values though we assumed that it would be a vector of
values. This is identified after verifying that the values assigned to
are just values of
.
Seeing that the equations for declination angle and hourly angle of sun rising are standard equations, it seems that there is a small implementation issue.
A function to automatically determine the best time-scale of the SPEI that better matches a given (dependent) time series.
Treating time as Date has some advantages as it opens up the possibility to use ggplot2::scale_date() options.
if (length(x.mon) == 0) {
spei[f] <- NA
next()
}
if (is.na(x.mon_sd) || (x.mon_sd == 0)) {
spei[f] <- NA
next()
}
if (length(x.mon) < 4) {
spei[ff, s] <- NA
coef[, s, c] <- NA
next()
}
When handling exceptions in a two-layer loop (one for n_sites s, another for ts_freq c), why does the spei matrix sometimes specify one subscript (spei[f]) and sometimes two subscripts (spei[ff,s])? I think the subscript s is essential.
Hi all,
what is the recommended file for the mask? I saw some papers use annual precipitation>70mm and 180mm to avoid dry areas but I am not sure which one to use. Can you please give some information and examples, please?
Best wishes,
Solo
Hi,
I am using this nice function to calculate future drought occurence globally.
I computed the waterbalance using thorntwaite PET from tas deducted from precipitation data.
However, some locations on the planet, in the future stages (e.g. 2100, nlyr = 1572), are NA
I have done some analysis of some of these locations passing the waterbalance timeseries into the spei computation:
e.g. for waterbalance layer 1501:1572 (2095 Jan-2100 Dec) we have values (in mm/month):
27.952274 21.689123 14.123683 17.460701 15.812398 37.006592 -66.429031 -259.123688 -220.037247 -97.774490 16.421326 19.157841 8.140391 9.198980 10.007673 6.265563 16.597578 29.495974 -100.427887 -332.850922 -331.282867 -96.347923 22.364281 9.272121 11.917697 23.926107 16.230862 27.928892 9.588178 19.053209 5.622412 -274.853882 -356.673981 -155.222855 -15.708746 17.407471 23.696455 25.058372 8.793851 14.453787 22.954494 18.429659 -32.144138 -337.259491 -323.165253 -114.420425 -12.792349 22.798891 12.963151 21.595062 14.063710 37.609177 16.736898 20.830385 -152.715103 -376.798645 -339.518524 -124.014435 -15.229343 11.399895 11.069696 11.272403 2.432789 15.543382 5.513311 3.631964 20.173397 -59.663048 -119.842651 -238.099121 -6.724354 17.916309 23.279354
Passing it into SPEI spei(data = wb_ts[1501:1572], scale = 3, na.rm = F, verbose = F)
Passing wb_ts[1524:1572] or +1524 starts returning non-finite values.
However, what is critical is that when the entire gcm + historical reference is passed to SPEI, some of the values are again NA, even if they are not NA in subsets (1501:1572 e.g.).
Would love to understand why this occurs.
This code will produce an error, although it should not:
tmin <- matrix(1:100, 10, 10)
tmax <- matrix(1:100, 10, 10)
wind <- matrix(1:100, 10, 10)
cc <- matrix(1:100, 10, 10)
lat <- 1:10
z <- 1:10
penman(Tmin = tmin, Tmax = tmax, U2 = wind, lat = lat, CC = cc, z = z)
The following error and warning are produced:
Error in `/.default`(0.00163 * P, lambda) : non-conformable arrays
In addition: Warning message:
In if (is.na(z)) { :
the condition has length > 1 and only the first element will be used
The error is slightly cryptic, but it comes from this line:
gamma <- 1.63e-3*P/lambda
where lambda
and P
are calculated by
lambda <- 2.501 - 2.361e-3*T
P0 <- matrix(101.3, n, m)
P <- P0 %*% as.matrix(((293 - 0.0065 * z)/293)^5.26)
Which means that P
and lambda
have different sizes, thus preventing P
from being divided by lambda
. The issue here seems to be in the matrix multiplication, %*%
.
If only a single observatory is used in the input with n
timesteps, then lambda
will be a matrix with n
rows and one column, z
will be a single element, P0
will be a matrix with n
rows and one column, and consequently %*%
will resolve to have P
as a matrix with n
rows and one column. This allows P/lambda
to evaluate correctly as elementwise division.
However, if m
observatories are used in the input, each with n
timesteps, then lambda
will be a matrix with n
rows and m
columns, z
will be a vector with m
elements, P0
will be a matrix with n
rows and m
columns, and consequently %*%
will resolve to have P
as a matrix with dimensions n x m %*% m x 1 = n x 1
. Thus, P/lambda
cannot evaluate correctly as elementwise division, because !all(dim(P) == dim(lambda))
.
To fix this problem, I would suggest changing the matrix multiplication to elementwise multiplication (which seems, to me at least, be the actual desired operation - it looks like using matrix multiplication instead was accidental). To allow that to work correctly, z
would have to be expanded to a correctly-sized matrix first, by using rep
and matrix
somehow.
I'm going to take a look at fixing it myself, and if I manage to come up with a solution, I'll submit a pull request with the changes (and perhaps tests as well).
I've calculated SPI at every grid cell using monthly rainfall in all of the CMIP5 models, for scale=3 and scale=6, using a Gamma distribution and a rectangular window type. It seems that infinity SPI values result in rare occasions when the 3 or 6 precip values are zero or extremely close to zero (I'm seeing this over the Sahara for example). The higher the scale, the fewer infinity values result. Perhaps in these cases, the SPI should be artificially set to -2, or to NaN?
I am suggesting the following correction in your website, page About the SPEI, Section Standardization of the variable:
Parameters of the Log-logistic distribution can be obtained following different procedures. Among them, the L-moment procedure is the most robust and easy approach (Ahmad et al., 1988). When L-moments are calculated, the parameters of the
Pearson IIILog-logistic distribution can be obtained following Singh et al. (1993):
The generalize etreme-value distribution is suggested for SPEI by Stagge et al. 2015. There are already functions for it in lmom
(lmom::pelgev()
, lmon::cdfgev()
), so I would think it might not be difficult to add.
Using curl, or similar.
I am having a problem getting the SPEI Hargreaves function to calculate monthly PET for multiple sites. I pass minimum temperature and maximum temperature as matrices (12 months and 10 sites) and latitude as a vector with the same length as the number of sites. I am getting warning messages about longer object length not being a multiple of shorter object length (see below). Am I doing something wrong?
dim(MinTest)
[1] 12 10
dim(MaxTest)
[1] 12 10
length(LatTest)
[1] 10
har_test <- hargreaves(MinTest,MaxTest,Ra = NA,lat = LatTest)
Warning messages:
1: In -tan(latr) * tan(delta) :
longer object length is not a multiple of shorter object length
2: In omegas * sin(latr) :
longer object length is not a multiple of shorter object length
3: In cos(latr) * cos(delta) :
longer object length is not a multiple of shorter object length
Hi,
I am trying to compute the SPI using parameters from another computation.
Here the line of code:
spi3_new=spi(var$value, 3, params=spi3$coefficients, verbose=FALSE, na.rm=TRUE)
But in some cases I get the following error:
Error in lmom::cdfgam(x[ff], f_params) :
missing values in parameter vector
Calls: spi -> spei -> <Anonymous>
Execution halted
Any suggestion on how to solve this?
With SPEI v1.7 I can compute SPEI using params=... without issues.
Best,
paolo
hello,
I would like to compute the SPEI 3-month index using both PET from thornthwaite and penman methods.
I am using global monthly data for about 16,000 gridpoints.
For thornthwaite PET I am using the tas
CMIP6 variable and latitude.
pet=list()
for (i in 1:length(var)) {
pet[[i]]=thornthwaite(Tave=var_value[[i]],
lat=var_lat[[i]][[1]],
na.rm = TRUE)
}
and global annual medians look fine, as follows:
The problem is SPEI with PET computed from penman method. Here I am using latitude, z and the following cmip6 variables (SPEI R package v1.8): tasmin
, tasmax
and clt
.
pet=list()
for (i in 1:length(var_min_value)) {
pet[[i]]=penman(Tmin = var_min_value[[i]],
Tmax = var_max_value[[i]],
CC = var_clt_value[[i]],
z = z_vec[i],
lat = var_min_lat[[i]][[1]],
U2 = NULL,
Ra = NULL,
Rs = NULL,
tsun = NULL,
ed = NULL,
Tdew = NULL,
RH = NULL,
P = NULL,
P0 = NULL,
CO2 = NULL,
na.rm = TRUE,
crop = "short",
method = "ICID",
verbose = TRUE)
}
But the global annual medians look as follow and are very different from the ones computed with PET thornthwaite:
Am I doing something wrong?
Thanks for any help.
Paolo
Hi,
When I load the package I see the following warning message:
> library(SPEI)
# Package SPEI (1.8) loaded [try SPEINews()].
Warning messages:
1: replacing previous import ‘lmom::cdfgam’ by ‘lmomco::cdfgam’ when loading ‘SPEI’
2: replacing previous import ‘lmom::cdfpe3’ by ‘lmomco::cdfpe3’ when loading ‘SPEI’
I think this is an error since in the NAMESPACE file you are loading importFrom(lmomco,cdfpe3)
here but inside the function spei, in this line you are using the same function from the package 'lmom'.
Could you correct this in order that the warning doesn't appear?
Thank you,
Eva
I have detected an error when applying the Thornwaite function to a temperature timeserie where the mean of the temperature is <0 for all the months.
In line 66 of the code of the thornwaite.R function, you set the T matrix values of a specific month to 0 when the mean of this month's temperatures is negative (T[T<0] <- 0). When the mean temperature for all the months is negative, this implies that the J matrix is also null (all its elements are =0), and thus in line 76 the result is NaN or Inf.
This situation is quite common in alpine environments.
Hi,
I tried to analyse a time series of the water balance 'DataWaterBalance' using spei (aggregation over four months starting from January 2013 until December 2017). Where do all the NA's in my result come from (especially for May, June and October)?
This is my dataset:
DataWaterBalance
Jan Feb Mar Apr May Jun Jul Aug
2013 44.379560 39.407684 21.562829 -24.299970 47.503552 -37.464860 -91.634212 -71.434604
2014 53.067473 43.866450 -36.911638 -50.963592 -13.763198 -67.691191 43.378232 68.080230
2015 92.641825 35.884504 8.830966 -44.549551 -63.924239 -74.143715 -80.702792 -3.758470
2016 96.391935 82.837027 35.548819 12.616174 -19.708125 31.203054 -57.579186 -69.207669
2017 24.116392 50.623918 10.143826 -58.697190 -66.739512 -92.584874 6.082707 -20.811211
Sep Oct Nov Dec
2013 31.166592 80.287287 83.802351 54.771282
2014 -40.233815 42.079559 41.352519 83.517715
2015 36.226553 3.940226 86.975420 38.772885
2016 -39.830591 22.390467 54.360755 9.304138
2017 40.940572 35.029547 80.916921 108.675360
This is my result:
SPEI <- spei(DataWaterBalance, scale =4)
SPEI
Jan Feb Mar Apr May Jun Jul
2013 NA NA NA 0.33216038 NA NA 0.24659491
2014 NA NA NA -1.01494215 NA NA 0.44540983
2015 NA NA NA 0.47583043 NA NA -1.21875803
2016 NA NA NA 1.46151624 NA NA 1.12388023
2017 NA NA NA -0.59834429 NA NA -0.82578210
Aug Sep Oct Nov Dec
2013 0.08609257 -1.10921341 NA -0.12138666 0.81098577
2014 1.45984189 1.35213116 NA -0.64499892 -0.61207794
2015 -1.19831116 -0.10885634 NA -0.14754493 -0.21176235
2016 0.52253486 -0.35520876 NA -1.87008029 -1.26423284
2017 -0.22246731 0.71017826 NA 1.79802481 1.01404395
str(SPEI)
List of 8
$ call : language spei(data = DataWaterBalance, scale = 4)
$ fitted : Time-Series [1:60, 1] from 2013 to 2018: NA NA NA 0.332 NA ...
..- attr(, "dimnames")=List of 2
.. ..$ : NULL
.. ..$ : chr "Series 1"
$ coefficients: num [1:3, 1, 1:12] NA NA NA NA NA ...
..- attr(, "dimnames")=List of 3
.. ..$ par: chr [1:3] "xi" "alpha" "kappa"
.. ..$ : chr "Series 1"
.. ..$ : NULL
$ scale : num 4
$ kernel :List of 3
..$ type : chr "rectangular"
..$ shift : num 0
..$ values: num [1:4] 0.25 0.25 0.25 0.25
$ distribution: chr "log-Logistic"
$ fit : chr "ub-pwm"
$ na.action : logi FALSE
What did I do wrong?
Thanks!
I'd like to use the SPEI package to calculate the drought index using a time series with a higher frequency (10 days, weekly). I've seen that the SPEI github version (1.7.2) will allow that but the version on CRAN (1.7) will not. Any chance of the newer version (with other improvements, I believe) making it into CRAN? Is this package still being maintained?
I am calculating SPI using this nice package, and I have an issue understanding the spi
documentation regarding the choice of reference period.
Basically, the docs seem to suggest that ref.start
and ref.end
can be used to control the reference period, independently of each other. If one is set to NULL, it will default to the first (or last) timestep.
However, this does not seem to work in my testing:
library(SPEI)
data(wichita)
prcp <- ts(wichita[,-c(1,2)], end=c(2011,10), frequency=12)[,'PRCP']
spiv = function(...) as.vector(fitted(spi(...)))[-(1:11)]
firsty = floor(as.vector(time(prcp))[1])
firstm = (as.vector(time(prcp))[1] %% 1) * 12 + 1
lasty = floor(as.vector(time(prcp))[length(prcp)])
lastm = (as.vector(time(prcp))[length(prcp)] %% 1) * 12 + 1
#Reference, full time series
spi_fullref = spiv(prcp, 12)
spi_Sfirst = spiv(prcp, 12, ref.start = c(firsty, firstm))
all(spi_Sfirst == spi_fullref)
#TRUE :)
spi_Elast = spiv(prcp, 12, ref.end = c(lasty, lastm))
all(spi_Elast == spi_fullref)
#TRUE :)
spi_SfirstElast = spiv(prcp, 12, ref.start = c(firsty,firstm), ref.end = c(lasty, lastm))
all(spi_SfirstElast == spi_fullref)
#TRUE :)
spi_SfirstE200001 = spiv(prcp, 12, ref.start = c(firsty,firstm), ref.end = c(2000, 01))
all(spi_SfirstE200001 == spi_fullref)
#FALSE :)
spi_E200001 = spiv(prcp, 12, ref.end = c(2000, 01))
all(spi_E200001 == spi_fullref)
#TRUE :(
spi_S199001 = spiv(prcp, 12, ref.start = c(1990, 01))
all(spi_S199001 == spi_fullref)
#TRUE :(
spi_S198002 = spiv(prcp, 12, ref.start = c(firsty, firstm+1))
all(spi_S198002 == spi_fullref)
#TRUE :(
spi_E199001 = spiv(prcp, 12, ref.end = c(1990, 01))
all(spi_E199001 == spi_fullref)
#TRUE :(
It seems that the behaviour is consistent only if both ref.start
and ref.end
are present, otherwise they are ignored if only one is. Is this a mistake on my part, or an unclear point in the docs?
Función para Penman-Monteith con datos diarios
sorry if this is a missunderstanding on my behalf about how the index is calculated, but my input data is from 1963- Jan 2023. The spi is only calculated up to Jan 2022.
Hi,
Me and @prebollo are trying to calculate ETP for Castilla y León using thornthwaite(). I have noticed that the function is not working as before, since you cannot calculate ETP for just one temperature value. Maybe I am missing something but could you confirm if something is going wrong? Thanks! Here a reproduccible example:
library(SPEI)
#> # Package SPEI (1.8.1) loaded [try SPEINews()].
meantemp <- c(2.18, 12.19, 27.33)
lati <- 41.47
thornthwaite(Tave = meantemp, lat = lati) #Ok
#> [1] "Checking for missing values (`NA`): all the data must be complete. Input type is vector. Assuming the data are monthly time series starting in January, all regular (non-leap) years."
#> [1] 15.40596 59.55327 139.12358
thornthwaite(Tave = meantemp[1], lat = lati) #It worked before with just one temperature value
#> [1] "Checking for missing values (`NA`): all the data must be complete. Input type is vector. Assuming the data are monthly time series starting in January, all regular (non-leap) years."
#> Error in apply(Tt, c(2, 3), function(x) {: 'MARGIN' does not match dim(X)
Created on 2023-07-26 with reprex v2.0.2
Optimize spei function for calculating the index at various time scales in one run.
Based on the package's example:
library(SPEI)
data("wichita")
wichita$PET <- thornthwaite(wichita$TMED, 37.6475)
wichita$BAL <- wichita$PRCP-wichita$PET
wichita <- ts(wichita[,-c(1,2)], end=c(2011,10), frequency=12)
spei12 <- spei(wichita[,'BAL'], 12)
Since events duration, peak and severity can be obtain from spei
output, it would be great to attach a table with the summary of these.
Some thoughts using dplyr
:
data.frame(year = c(time(spei12$fitted)) %/% 1,
month = c(cycle(spei12$fitted)),
values = c(spei12$fitted)) %>%
filter(complete.cases(.)) %>%
mutate(group = with(rle(sign(values)),rep(seq_along(values), lengths))) %>%
group_by(group) %>%
summarise(duration = n(),
peak = ifelse(max(values)<0,min(values),max(values)),
severity = sum(values),
start = paste0(first(year),'-',sprintf("%02d",first(month))),
end = paste0(last(year),'-',sprintf("%02d",last(month))))
# A tibble: 43 × 6
group duration peak severity start end
<int> <int> <dbl> <dbl> <chr> <chr>
1 1 18 -1.92 -20.2 1980-12 1982-05
2 2 4 0.596 1.76 1982-06 1982-09
3 3 6 -0.730 -2.64 1982-10 1983-03
4 4 1 0.283 0.283 1983-04 1983-04
5 5 2 -0.187 -0.267 1983-05 1983-06
6 6 11 0.924 6.41 1983-07 1984-05
7 7 15 -1.23 -10.3 1984-06 1985-08
8 8 6 0.764 2.36 1985-09 1986-02
9 9 2 -0.0715 -0.0887 1986-03 1986-04
10 10 2 0.0430 0.0739 1986-05 1986-06
# … with 33 more rows
What do you think?
Hello, when I try to run a SPI-3 with triangular kernel and coefficients in "param=" from another SPI file with the same dimensions I get the following error:
Error in qnorm(pze + (1 - pze) * pnorm(std[ff, s])) :
object 'pze' not found
I am unsure how to solve this. I have attached two of the datasets I am using and a section of annotated script that should show my thought process. Maybe that will provide insights into my issue. a
Thank you for your help
Hola, he visto que en la ecuación de Penman, en las ecuaciones pones por ejemplo: "Saturation vapour pressure at tmx (eq. 1.10, p. 66)".
Quisiera saber que fuente utilizaste para poder encontrar esa ecuación 1.10 de la página 66, muchas gracias!
Hi, I'm trying to use a 3d gridded water balance dataset (dimension: time 240 x lat 192 x lon 288) as input to calculate SPEI, but when I ran the script, it showed 'No time information provided, assuming a monthly time series'. I checked the example input cruts4.rda, it has the dimension of 1440 x 2 x 3, I'm not sure which number refers to the number of time steps here. I would really appreciate it if you could inform me of the correct dimension of the input data and how we should provide the time information in the 3d array.
Dear Sbegueria,
Thanks a lot for providing the R code to compute SPEI!
I have calculated spei as the notebook said, but the result shows that the probability distribution function of spei is not like stardard normal distribution, just like the picture shows. Is it due to my code error or other reasons?
Thank you very much !
Here is the probability distribution function of spei:
Here is the R code:
library(tidyverse)
library(data.table)
library(ncdf4)
library(SPEI)
library(dplyr)
library(sp)
library(raster)
library(sf)
library(terra)
precnc<- nc_open("D:\1_Drought_Resilience\Data\Meteorology\prec_monthly_1982_2019_0083.nc")
tempnc<- nc_open("D:\1_Drought_Resilience\Data\Meteorology\temp_monthly_1982_2019_0083.nc")
lon <- ncvar_get(precnc,'lon')
lat <- ncvar_get(precnc,'lat')
time<- ncvar_get(precnc,'time')
prec<- ncvar_get(precnc,'prec') # size(456time133lat250lon)
temp<- ncvar_get(tempnc,'temp')# size(456time133lat250lon)
dem_file = "D:\1_Drought_Resilience\Arcgis\dem\dem_0083.tif"
dem<-raster(dem_file)
demdata<-as.matrix(dem)
speidata<-array(-9999, dim=c(133,250,456))
for (row in seq(133)){
for (col in seq(250)){
if (!is.na(dem[row, col])){
pet_series <- thornthwaite(temp[col,row,], lat[row], na.rm = TRUE, verbose=FALSE)
wb_series<-prec[col,row,]-pet_series
spei_series<-spei(wb_series, 3, na.rm = TRUE, verbose=FALSE)$fitted
speidata[row,col,]=spei_series
}
}
}
When calling spi() the info printed to screen says 'Calculating the Standardized Precipitation Evapotranspiration Index (SPEI)...'.
Hi all,
When I use the basic Hargreaves PET estimate it works correctly:
HA <-hargreaves(Tmin=monthly_tmin[,3], Tmax=monthly_tmax[,3], lat=Lat)
However when I use rainfall to calculate PET with Droogers and Allen method:
DA <-hargreaves(Tmin=monthly_tmin[,3], Tmax=monthly_tmax[,3], lat=Lat, Pre = monthly_rain[,3])
, using the same data on monthly basis I get this output and error:
[1] "Calculating reference evapotranspiration using the Hargreaves method. Using latitude (lat
) to estimate extraterrestrial radiation. Using precipitation data, following Droogers and Allen (2002). Checking for missing values (NA
): all the data must be complete. Input type is array. Assuming the data are monthly time series starting in January, all regular (non-leap) years."
Error in is.nan(ab^0.76) : default method not implemented for type 'list'.
Does anyone know a fix for this?
Include new dataset (for example, weekly) and provide an example of using the functions with frequencies other than monthly.
Hi! I'm happy to see this package alive again!
I've used some of the code to calculate the spi for another package and now we'll be able to add SPEI as a dependency. One thing I realize while doing some tests is that you are printing the warnings you collect in the spei()
function using print()
and that generates a lot of text in the console. I know you can avoid that by using verbose = FALSE
but I think that using the warning()
function instead of print()
is a better practice, that way, R will recognize the text as a warning instead of random text.
Hi
Sometimes I get ”-Inf “ as SPEI result for months with the lowest climatic water balance (even when it’s not an outstanding value). I know that "-Inf" stands for infinity (when dividing by zero) or the result that can’t be carried out at all. What is the reason I get that error calculating SPEI? How can I debug it? I use the default - log-Logistic distribution and ub-pwm method for parameter fitting.
I would be grateful for any help and tips regarding this topic.
Barbara
Revisar y si es necesario corregir tema unidades de variable viento en función Penman
This seems to only happen in certain configurations / OS.
I just wonder whether we can compute SPEI based on HAPPI data which has a temporal coverage of 10-year ? As McKee et al., 1993 suggest that the analysis and calculation of drought characteristics need data from a long-term period of typically > 20 consecutive years.
If I use 10-year dataset, the result will be accurate and realizable?
Hi,
I am investigating the effects of drought on bird productivity using the SPEI, but I am not sure what is the best way to compute it.
I have daily data for precipitation and potential evapotranspiration, so I first computed daily SPEI values using:
meteo_ts <- ts(as.matrix(meteo_t[,-1]), start = c(1990, 1), frequency = 365)
spei_ts <- spei(meteo_ts, 1)
Now, I want to have SPEI values for longer periods (e.g. over spring) and I am a bit confused about the difference between:
I tried the different methods and my models don't give the same results depending on the method used to compute the SPEI.
Are these 3 methods correct ?
Which one should I use to compute the SPEI over spring ?
Is it possible to calculate both indices for a gridded dataset? I am new to coding and struggling a lot. Please help me. What changes should I make in the code line to calculate it for a CSV file with gridded rainfall and temperature dataset?
As reported by email by a user:
Hi Santiago,
I’m using the SPEI R package for my research and I wanted to ask you about dealing with missing values.
I have a time series with quite a lot of missing values (see attached figure). The package seems to work fine when the scale is set to 1 (and na.rm=TRUE). However, I noticed for scales >1, the code replaces the missing values with some climatological value. Presumably the code then uses these values in the calculation as in my case, the code doesn’t produce any negative SPI values using scale=6. By definition, this shouldn’t really be possible.
If you have a fix to this problem, would you be able to kindly let me know?
Many thanks,
Anna
Why convert negative ET to 0? When using daily ET to sum to monthly, whether negative values need to be converted to 0?
Incorporar diferentes opciones de cálculo para la función Penman. Utilizar el código que ya preparó Miquel.
Cambiar la función SPEI::plot por la nueva versión basada en ggplot2.
Excecuting the code below returns a time series of NA for the SPI calulation using a fit of 'max-lik'
The code works fine with the 'ub-pwm' fit. Any help would be geat!
library(SPEI)
date1 <- '1991-01-01'
date2 <- '2022-12-31'
# Vector of precip data
prcp <- c(12.385, 14.56, 84.177, 82.407, 140.11, 71.865, 122.404, 19.689, 74.63, 106.985, 104.498, 29.507,
25.848, 23.135, 32.936, 52.319, 61.574, 51.701, 70.253, 82.455, 102.266, 38.425, 118.912, 56.103,
35.346, 1.337, 8.652, 76.22, 124.201, 137.701, 55.681, 87.971, 85.293, 48.03, 43.44, 11.535,
24.986, 15.565, 38.001, 55.143, 51.189, 67.051, 127.859, 62.913, 147.208, 52.577, 45.874, 3.914,
17.281, 8.121, 49.453, 57.111, 95.307, 41.837, 83.787, 173.801, 69.909, 124.574, 40.477, 56.383,
92.18, 31.096, 45.262, 100.924, 30.166, 129.566, 151.449, 48.891, 101.847, 78.021, 25.922, 84.927,
70.358, 6.09, 51.512, 18.66, 67.187, 94.862, 57.436, 100.444, 58.134, 92.501, 9.297, 17.738, 63.015,
33.73, 83.186, 40.893, 31.306, 85.689, 43.181, 68.625, 38.336, 56.033, 56.388, 25.188, 67.26,
46.581, 5.931, 42.391, 157.64, 76.645, 274.669, 73.131, 54.014, 52.27, 25.362, 23.102, 41.704,
34.995, 53.772, 59.42, 50.702, 114.356, 145.441, 87.555, 138.506, 19.834, 56.441, 28.874, 31.283,
33.95, 15.962, 72.31, 86.051, 96.976, 55.149, 42.773, 86.452, 63.163, 55.593, 34.201, 6.104, 44.355,
72.547, 140.646, 73.256, 80.686, 87.629, 91.156, 78.412, 182.947, 11.309, 10.609, 7.404, 37.726,
78.151, 74.319, 72.562, 61.255, 26.069, 134.898, 97.566, 31.052, 48.441, 39.8, 24.741, 48.004,
96.378, 53.094, 100.726, 81.675, 103.615, 70.379, 41.732, 114.762, 29.506, 47.318, 28.767, 27.808,
18.898, 34.903, 77.017, 78.357, 76.733, 55.887, 69.255, 149.134, 71.69, 29.588, 34.341, 34.929,
35.232, 19.747, 145.687, 31.257, 82.48, 119.92, 65.942, 48.313, 45.942, 48.417, 23.48, 18.238,
42.067, 42.48, 40.272, 65.081, 53.738, 38.337, 76.987, 147.274, 15.899, 61.78, 39.436, 30.22,
21.472, 123.231, 73.043, 106.254, 62.813, 15.926, 57.42, 49.503, 30.557, 54.914, 15.794, 29.734,
18.37, 111.956, 84.803, 55.557, 46.68, 76.849, 31.811, 116.134, 16.584, 55.444, 13.689, 10.121,
15.546, 10.445, 34.91, 178.911, 196.371, 68.862, 190.498, 64.618, 54.982, 32.544, 14.395, 3.747,
42.236, 86.608, 99.329, 94.798, 46.932, 33.443, 89.661, 40.399, 30.978, 36.376, 31.049, 27.903,
35.629, 31.926, 115.1832, 49.418, 79.482, 34.024, 53.833, 85.008, 34.768, 35.674, 32.502, 36.513,
42.602, 99.468, 79.037, 90.192, 101.719, 77.357, 51.073, 66.202, 69.336, 33.474, 34.997, 34.114,
31.174, 87.496, 69.826, 88.95, 38.837, 108.239, 164.872, 84.869, 71.43, 53.455, 15.693, 6.145,
18.74, 79.687, 125.433, 89.968, 65.675, 91.385, 78.546, 74.637, 67.385, 102.195, 22.46, 22.227,
73.878, 65.999, 55.27, 88.588, 93.457, 84.378, 109.766, 115.427, 43.971, 50.174, 36.989, 37.836,
27.074, 158.36, 120.466, 177.778, 68.125, 102.783, 58.884, 84.327, 34.88, 47.297, 28.806, 30.719,
16.388, 61.368, 59.829, 104.492, 70.354, 88.753, 120.826, 173.388, 55.717, 32.44, 30.041, 108.874,
28.476, 78.3, 128.971, 40.769, 100.428, 67.155, 124.736, 108.245, 31.703, 107.648, 47.778, 11.688,
75.845, 68.2, 55.504, 130.53, 195.374, 105.965, 94.044, 67.995, 58.563, 15.757, 15.1248, 30.168,
45.9477, 76.3019, 41.0862, 106.5615, 84.8749, 64.9139, 74.4176, 18.4552, 24.8467, 65.7223, 19.3086,
20.6611, 69.5475, 79.5091, 117.4526, 87.4791, 39.3405, 110.511, 37.1871, 28.1281, 68.0051, 39.1535)
# Build the date frame of the data
dates <- seq(as.Date(date1, "%Y-%m-%d"), as.Date(date2, "%Y-%m-%d"), by = "month")
months <- as.numeric(format(dates, "%m"))
years <- as.numeric(format(dates, "%Y"))
data <- data.frame(years, months, prcp)
# Compute 1-month SPI
spi1_ub_pwm <- spi(prcp, 1, fit='ub-pwm')
spi1_max_lik <- spi(prcp, 1, fit="max-lik")
print(spi1_ub_pwm)
print(spi1_max_lik)
Milly and Dune (2016) investigate the Penman-Monteith method for calculating PET and find that it overestimates drought compared to non-water-stressed evapotranspiration (which should theoretically be equal). They propose a simplification of Penman-Monteith that better predicts PET: PET = 0.8(R_n - G) where R_n is net radiation at the surface, and G is heat flux into the subsurface, both converted to units of mm/d. This might be a nice addition to the SPEI package.
Milly PCD, Dunne KA (2016) Potential evapotranspiration and continental drying. Nature Clim Change 6:946–949. https://doi.org/10.1038/nclimate3046
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.