How to calculate monthly NDVI raster with R - r

NDVI RasterStack
I have a 15day 1981-2015 NDVI RasterStack.
I need to calculate monthly NDVI with the 15d data.
I want to know how to calculate mean of the same names MM raster into a new monthly 1981-2015 rasterstack
I appreciate for your help! Thank you very much.
names XYYYY.MM.DD

I have recently been working on the same solution to you problem, this should work for you also.
You want to create a separate variable that contains the dates from your layer names.
#this removes the "X" character from the name leaving only the dates
layer_name <- sub('.', '', names(NDVI_stack))
#install.packages("lubridate")
library(lubridate)
layer_name <- ymd(layer_name)
#Create an indices to prepare it for stackApply, which takes the means for all the days of the month within each year.
indices <- format(as.Date(layer_name, format = "%Y.%m.%d"), format = "%Y.m")
NDVI_mean <- stackApply(NDVI_stack, indices, mean)

Related

calculate mean from list of rasters and and save it in a different name

I have a list of rasters(.tif format) for multiple years. It is a 16 day NDVI from landsat, i want to make a monthly NDVI (average of two consecutive rasters) and save it in same or different directory as a monthly average
I have listed the raster rasters and make stack of it, later i used stackApply to calculate the mean, but it will produce empty raster. I have 23 images for single year, which i want to average it and make 12 months. This is how my raster files look like
"landsatNDVISC05SLC2000001.tif" "landsatNDVISC05SLC2000017.tif"
"landsatNDVISC05SLC2000033.tif" "landsatNDVISC05SLC2000049.tif"
"landsatNDVISC05SLC2000065.tif" "landsatNDVISC05SLC2000081.tif"
"landsatNDVISC05SLC2000097.tif" "landsatNDVISC05SLC2000113.tif"
"landsatNDVISC05SLC2000129.tif" "landsatNDVISC05SLC2000145.tif"
"landsatNDVISC05SLC2000161.tif" "landsatNDVISC05SLC2000177.tif"
"landsatNDVISC05SLC2000193.tif" "landsatNDVISC05SLC2000209.tif"
"landsatNDVISC05SLC2000225.tif" "landsatNDVISC05SLC2000241.tif"
"landsatNDVISC05SLC2000257.tif" "landsatNDVISC05SLC2000273.tif"
"landsatNDVISC05SLC2000289.tif" "landsatNDVISC05SLC2000305.tif"
"landsatNDVISC05SLC2000321.tif" "landsatNDVISC05SLC2000337.tif"
"landsatNDVISC05SLC2000353.tif
This code works but will produce more than twelve empty raster and i also want to save the raster brick as single subset monthly raster
library(raster)
lrast<-list.files("G:/LANDSAT-NDVI/testAverage")
layers<-paste("landsatNDVISC05SLC2000", seq(from=001, to=353,by=16))
stak<-stack(lrast)
raster<-stackApply(stak, layers, fun = mean)
I want to make a monthly average from landsatNDVISC05SLC2000001.tif and landsatNDVISC05SLC2000017.tif as landsatNDVISC05SLC2000M1.tif. Similarly, 33,49 and since i only have 23 raster, i want to retain landsatNDVISC05SLC2000353.tif as landsatNDVISC05SLC2000M12.tif
Blockquote
not sure how stackapply works but something like this should do the stuff needed.
library(raster)
files <- list.files(path = "...", full.names = T, pattern = ".tif")
stk <- stack()
for (i in files){
print(i)
as <- raster(files[i])
stk <- addLayer(stk, as)
}
jday <-c("landsatNDVISC05SLC2000017.tif","landsatNDVISC05SLC2000033.tif",
"landsatNDVISC05SLC2000049.tif","landsatNDVISC05SLC2000065.tif","landsatNDVISC05SLC2000081.tif",
"landsatNDVISC05SLC2000097.tif","landsatNDVISC05SLC2000113.tif","landsatNDVISC05SLC2000129.tif",
"landsatNDVISC05SLC2000145.tif","landsatNDVISC05SLC2000161.tif","landsatNDVISC05SLC2000177.tif",
"landsatNDVISC05SLC2000193.tif","landsatNDVISC05SLC2000209.tif","landsatNDVISC05SLC2000225.tif",
"landsatNDVISC05SLC2000241.tif","landsatNDVISC05SLC2000257.tif","landsatNDVISC05SLC2000273.tif",
"landsatNDVISC05SLC2000289.tif","landsatNDVISC05SLC2000305.tif","landsatNDVISC05SLC2000321.tif",
"landsatNDVISC05SLC2000337.tif","landsatNDVISC05SLC2000353.tif")
jday <- as.numeric(substr(jday, 24, 25)) #substract the julien days (which I think these number represent before .tif; or you can substract the names from the 'files' vector)
dates <- as.Date(jday, origin=as.Date("2000-01-01")) # create a Date vector
stk <- setZ(stk, dates) # assign the date vector to the raster stack
raster <- zApply(stk, by = format(dates,"%Y-%m"), fun = mean, na.rm = T) # create the monthly stack

Creating time series in R

I have a CSV file containing data as follows-
date, group, integer_value
The date starts from 01-January-2013 to 31-October-2015 for the 20 groups contained in the data.
I want to create a time series for the 20 different groups. But the dates are not continuous and have sporadic gaps in it, hence-
group4series <- ts(group4, frequency = 365.25, start = c(2013,1,1))
works from programming point of view but is not correct due to gaps in data.
How can I use the 'date' column of the data to create the time series instead of the usual 'frequency' parameter of 'ts()' function?
Thanks!
You could use zoo::zoo instead of ts.
Since you don't provide sample data, let's generate daily data, and remove some days to introduce "gaps".
set.seed(2018)
dates <- seq(as.Date("2015/12/01"), as.Date("2016/07/01"), by = "1 day")
dates <- dates[sample(length(dates), 100)]
We construct a sample data.frame
df <- data.frame(
dates = dates,
val = cumsum(runif(length(dates))))
To turn df into a zoo timeseries, you can do the following
library(zoo)
ts <- with(df, zoo(val, dates))
Let's plot the timeseries
plot.zoo(ts)

Spatial polygon dataset + subset

I'm working with a spatial polygon dataframe.
data can be downloaded here:
http://geoportal.statistics.gov.uk/datasets/lower-layer-super-output-areas-december-2011-super-generalised-clipped-boundaries-in-england-and-wales
This contains the lower layer output area (lsoa) for England and Wales.
I need to subset the dataframe in order to keep only the polygons for the london lsoa11cd.
I have a list of lsoa11cd for London.
These are between E01000001 and E01004765. I'm not sure how to proceed to subset the spatial polygons (see image attached). Find below an attempt which does not work.
london <- shapefile[substr(shapefile#data$lsoa11cd, -7 , -1) <= 1004765, ]
london <- london[substr(london#data$lsoa11cd, -7 , -1) >= 1000001, ]
If I'm interpretting your question correctly, this should work nicely:
Use the shapefile function from the raster package to read-in the shapefile:
library(raster)
# Read-in the data. This will create a SpatialPolygonsDataFrame with 34,753 features
s <- shapefile('Lower_Layer_Super_Output_Areas_December_2011_Super_Generalised_Clipped__Boundaries_in_England_and_Wales.shp')
It looks like all of the lsoa11cd values have a letter and a number as the first two characters in the string. Let's first subset the data to keep only those with 'E' as the first chatacter for their lsoa11cd value.
s <- s[grep("^[aE].*", s$lsoa11cd), ]
Now we can remove the first two characters from each lsoa11cd string and convert to a numeric variable for easier subsetting as follows:
s$lsoa11cd <- as.numeric(substring(s$lsoa11cd, 3))
Then you can simply subset within the range you've specified:
s <- s[s$lsoa11cd %in% 1000001:1004765, ]

Monthly average from netCDF files in R

I have one netCDF file (.nc) with 16 years(1998 - 2014) worth of daily precipitation (5844 layers). The 3 dimensions are time (size 5844), latitude (size 19) and longitude (size 20)
Is there a straightforward approach in R to compute for each rastercell:
Monthly & yearly average
A cummulative comparison (e.g. jan-mar compared to the average of all jan-mar)
So far I have:
library(ncdf4)
library(raster)
Rname <- 'F:/extracted_rain.nc'
rainfall <- nc_open(Rname)
readRainfall <- ncvar_get(rainfall, "rain") #"rain" is float name
raster_rainfall <- raster(Rname, varname = "rain") # also tried brick()
asdatadates <- as.Date(rainfall$dim$time$vals/24, origin='1998-01-01') #The time interval is per 24 hours
My first challenge will be the compuatation of monthly averages for each raster cell. I'm not sure how best to proceed while keeping the ultimate goal (cummulative comparison) in mind. How can I easily access only days from a certain month?
raster(readRainfall[,,500])) # doesn't seem like a straightforward approach
Hopefully I made my question clear, a first push in the right direction would be much appreciated.
Sample data here
The question asked for a solution in R, but in case anyone is looking to do this task and wants a simple alternative command-line solution, these kind of statistics are the bread and butter of CDO
Monthly averages:
cdo monmean in.nc monmean.nc
Annual averages:
cdo yearmean in.nc yearmean.nc
Make the average of all the Jan, Feb etc:
cdo ymonmean in.nc ymonmean.nc
The monthly anomaly relative to the long term annual cycle:
cdo sub monmean.nc ymonmean.nc monanom.nc
Then you want a specific month, just select with selmon, or seldate.
you can call these functions from R using the system command.
Here is one approach using the zoo-package:
### first read the data
library(ncdf4)
library(raster)
library(zoo)
### use stack() instead of raster
stack_rainfall <- stack(Rname, varname = "rain")
### i renamed your "asdatadates" object for simplicity
dates <- as.Date(rainfall$dim$time$vals/24, origin='1998-01-01')
In your example dataset you only have 18 layers, all coming from January 1998. However, the following should also work with more layers (months).
First, we will build a function that operates one one vector of values (i.e. pixel time series) to convert the input to a zoo object using dates and the calculates the mean using aggregate. The function returns a vector with the length equal to the number of months in dates.
monthly_mean_stack <- function(x) {
require(zoo)
pixel.ts <- zoo(x, dates)
out <- as.numeric(aggregate(pixel.ts, as.yearmon, mean, na.rm=TRUE))
out[is.nan(out)] <- NA
return(out)
}
Then, depending on whether you want the output to be a vector / matrix / data frame or want to stay in the raster format, you can either apply the function over the cell values after retrieving them with getValues, or use the calc-function from the raster-package to create a raster output (this will be a raster stack with as many layers as there a months in your data)
v <- getValues(stack_rainfall) # every row displays one pixel (-time series)
# this should give you a matrix with ncol = number of months and nrow = number of pixel
means_matrix <- t(apply(v, 1, monthly_mean_stack))
means_stack <- calc(stack_rainfall, monthly_mean_stack)
When you're working with large raster datasets you can also apply your functions in parallel using the clusterR function. See ?clusterR
I think easiest to convert to raster brick and then into a data.frame.
Then can pull stats quite easily using general code DF$weeklymean <- rowMeans(DF[, ])

how to convert xts index or time to year

For annual data (such as Annual Income Statements), I would like to keep xts format but I need to convert the index of the table to "only year". There are yearmon and yearqtr classes but I did not find "year" only class to work with xts.
# IS is annual reports of incomes. time(IS) is POSIXct.
library(quantmod)
IS <- viewFin(get(getFin("IBM")), "IS", "A") # Download data
IS <- as.xts(t(IS)) # Convert to xts
time(IS) <- as.yearqtr(time(IS)) ## works to have quarterly index
time(IS) <- as.yearmon(time(IS)) ## works to have monthly index
time(IS) <- ????(time(IS)) ## To have yearly index with xts class
What is the best solution? Thank you.
It would be helpful if you explained why you need to have the index as "year" only. Xts has an indexFormat command that allows you to control how dates are displayed, and while I've never used it I assume it will allow you to display only the year of any given index entry.
A more extreme solution would be to convert every date to the first of the year in that year. Here's some code to help do this:
first.of.year <- function(x) # Given a date, returns the first day of that year
return(as.Date(paste(year(as.Date(x)),"-01-01", sep="")))
index(x) <- first.of.year(index(x))

Resources