AnesG
AnesG

Reputation: 275

How to repeat codes changing the variables in a sequence in R

This is the code I want to repeat

A_1981 <- Base[1:12]]
B <- sum(A_1981)
MFI_1981 <- sum(A_1981^2)/B

Base is a Raster brick

A_1981 is for a year

MFI_1981 is the final result

So i have to continue with the next year

A_1982 <- Base[13:24]]
B <- sum(A_1982)
MFI_1982 <- sum(A_1982^2)/B

To repeat the same code I think in replace values only in the names:

a <- seq(1,421,by=12)
b <- seq(12,432,by=12)
c <- seq(1981,2016, by=1)

And do it in sequence for the next third year, would be something like this

A_a[3] <- Base[[b[3]:c[3]]
B <- sum(A_a[3])
MFI_a[3] <- sum(A_[3]^2)/B

Have to be some way with for or make a function. But have no idea where to start.

Upvotes: 2

Views: 676

Answers (2)

Rui Barradas
Rui Barradas

Reputation: 76611

The following does what you want using mapply and creates only one object in the .GlobalEnv, which I named MFI.

I start by creating a vector Base, since you have not posted a dataset example.

set.seed(2469)    # Make the results reproducible

n <- 432
Base <- sample(100, n, TRUE)

step <- 12
b <- seq(1 + step, n, by = step)
a <- seq(1, n - step, by = step)

MFI <- mapply(function(i, j) sum(Base[i:j]^2)/sum(Base[i:j]), a, b)


head(MFI)
#[1] 63.66472 70.54014 67.60567 53.15550 58.71111 65.37008

Another way would be to use Map, like @Parfait suggests in his comment.

obj <- Map(function(i, j) sum(Base[i:j]^2)/sum(Base[i:j]), a, b)
names(obj) <- paste("MFI", 1980 + seq_along(obj), sep = "_")

obj$MFI_1981
#[1] 63.66472

Note that length(obj) is 35 and therefore the last obj is obj$MFI_2015 and not MFI_2016 like is said in the question. This can be easily solved by making n <- 444 right at the beginning of the code.

Upvotes: 2

Robert Hijmans
Robert Hijmans

Reputation: 47436

I think you are looking for something like this

Example data (48 layers, i.e, 4 "years")

library(raster)
f <- system.file("external/rlogo.grd", package="raster")
Base <- stack(rep(f, 4*4))

Approach 1

f <- function(year) {
    start <- (year-1981) * 12 + 1
    A <- Base[[start:(start+11)]]
    sum(A^2)/sum(A)
}

mfi <- lapply(1981:1984, f)
MFI <- stack(mfi)

Approach 2

for (year in 1981:1984) {
    start <- (year-1981) * 12 + 1
    A <- Base[[start:(start+11)]]
    mfi <- sum(A^2)/sum(A)
    writeRaster(mfi, paste0(year, ".tif"))
}

s <- stack(paste0(1981:1984, ".tif"))

Approach 3, with mapply as in Rui Barradas' answer, but fixed for when Base is a RasterBrick (and also including the last year)

n <- nlayers(Base)
a <- seq(1, n, by = 12)
mfi <- mapply(function(i, j) sum(Base[[i:j]]^2)/sum(Base[[i:j]]), a, a+11)
s <- stack(mfi)

Upvotes: 2

Related Questions