R Как рассчитать среднее сезонное значение для каждого года, используя stackApply? - PullRequest
1 голос
/ 02 октября 2019

Я хотел рассчитать среднее сезонное значение для каждого года, а не за весь период. Я определил свои сезоны следующим образом: DJF (декабрь-февраль), MAM (март-май), JJA (июнь-август) и SON (сентябрь-ноябрь).

Вдохновленный решением вопроса Фредрик , я создал индекс «groups», который представляет времена года, затем применил команду «stackApply», но этот вычисляет среднее сезонное значение за весь период. Я объясняю, что полученный последний слой содержит только 4 растра, но для моего случая я хотел вычислить «среднегодовое значение для каждого года, поэтому необходимо иметь 4 растра для каждого года, и всего в растре должно быть 136 растров.

Ниже моего кода

Спасибо за помощь

library(raster)
set.seed(123)
r <- raster(ncol=10, nrow=10)
r_brick <- brick(sapply(1:408, function(i) setValues(r, rnorm(ncell(r), i, 3))))
dim(r_brick)

dates <- seq(as.Date("1982-01-01"), as.Date("2015-12-31"), by="month")  
months <- format(dates, "%Y-%m")

groups <- function(x) {
  d <- as.POSIXlt(x)

  ans <- character(length(x))
  ans[d$mon %in%  c(11,0:1)] <- "DJF"
  ans[d$mon %in%  2:4] <- "MAM"
  ans[d$mon %in%  5:7] <- "JJA"
  ans[d$mon %in% 8:10] <- "SON"
  ans
}

data.frame(dates, groups(dates))

r_brick.s <- stackApply(r_brick, indices=groups(dates), fun=mean,na.rm=TRUE) 
nlayers(r_brick.s)

Ответы [ 2 ]

3 голосов
/ 03 октября 2019

Данные вашего примера

library(raster)
r <- raster(ncol=10, nrow=10)
b <- brick(sapply(1:408, function(i) setValues(r, rnorm(ncell(r), i, 3))))    
dates <- seq(as.Date("1982-01-01"), as.Date("2015-12-31"), by="month")  

Как указывает Маджид, если вы хотите группировать по годам, вам нужно использовать эти

years <- as.integer(format(dates, "%Y"))
months <- as.integer(format(dates, "%m"))

Теперь нужно сгруппировать месяцы. Обратите внимание, что начиная с декабря, вы должны убедиться, что не объединяете январь и декабрь одного и того же года. Скорее вы хотите объединить декабрь года i с январем и февралем года i + 1 . Вот один из способов сделать это (начать год в декабре!)

n <- length(months)

# move all months back one month   
mnt <- c(months[-1], ifelse(months[n] < 12, months[n]+1, 1)) 

# move the years along
yrs <- c(years[-1],  ifelse(months[n] < 12, years[n], years[n]+1)) 

# group by trimesters using integer division (or do: floor((mnt-1) / 3))
trims <- (mnt-1) %/% 3  

# get names instead of 0, 1, 2, 3
trimnms <- c("DJF", "MAM", "JJA", "SON")[trims + 1]

Объединить годы и имена

yt <- paste(yrs, trimnms, sep="_")

Использовать индекс

s <- stackApply(b, indices=yt, fun=mean, na.rm=TRUE) 

Если вышеописанный процесс перемещения месяцев назад затруднен, попробуйте сделать это с помощью нескольких дат (первые 15 или около того)

2 голосов
/ 03 октября 2019

С вашим сценарием все в порядке, за исключением групп, которые вы генерируете (например, DJF, ...). Индекс, который вы планируете использовать для групп, должен быть уникальным для каждой целевой группы, в то время как на данном этапе нет никакой разницы между JJA для 1982 года и JJA для 1983 года и т. Д.

#data.frame(dates, paste(substr(dates, 1,4), groups(dates), sep="_"))
idx <- paste(substr(dates, 1,4), groups(dates), sep="_")

r_brick.s <- stackApply(r_brick, indices=idx, fun=mean, na.rm=TRUE) 

nlayers(r_brick.s)
#136 that is the number of seasons
...