8

我有均匀的空间时间序列和每日平均观测数据。

我如何计算季节性手段最简单的方法?季节应遵循 DJF(=冬季:12 月、1 月、2 月)、MAM、JJA 和 SON 的气象命名法。

这意味着 12 月的值来自 x-1 年。

每月平均值的计算在这里很好地呈现: 如何计算每月平均值?

在计算季节性平均值时可以遵循这个想法。但是,有几个警告使它不是很透明,必须小心!

我还在以前的线程中处理了这个问题的一小部分:如何在 R 中切换行?

现在是完整的故事:

0:做一个随机的时间序列

ts.pdsi <- data.frame(date = seq(
                from=as.Date("1901-01-01"), 
                to=as.Date("2009-12-31"), 
                by="day"))
ts.pdsi$scPDSI <- rnorm(dim(ts.foo)[1],  mean=1, sd=1)    # add some data

第一:使用 seas 包并将季节添加到您的时间序列中,必须将其格式化为 data.frame。

library(seas)
# add moth/seasons
ts.pdsi$month  <- mkseas(ts.pdsi,"mon")   # add months
ts.pdsi$seas <- mkseas(ts.pdsi,"DJF")     # add seasons
ts.pdsi$seasyear <- paste(format(ts.pdsi[,1],"%Y"), 
                          ts.pdsi$seas ,sep="")   # add seasyears, e.g. 1950DJF

这给了

> head(ts.pdsi)
    date      scPDSI month seas seasyear
1 1901-01-01 -0.10881074   Jan  DJF  1901DJF
2 1901-02-01 -0.22287750   Feb  DJF  1901DJF
3 1901-03-01 -0.12233192   Mär  MAM  1901MAM
4 1901-04-01 -0.04440915   Apr  MAM  1901MAM
5 1901-05-01 -0.36334082   Mai  MAM  1901MAM
6 1901-06-01 -0.52079030   Jun  JJA  1901JJA

第二:然后您可以按照上述方法使用 $seasyear 列计算季节性平均值

> MEAN <- tapply(pdsi$scPDSI, ts.pdsi$seasyear, mean, na.rm = T)
> head(MEAN)
1901DJF     1901JJA     1901MAM     1901SON     1902DJF     1902JJA 
-0.45451556 -0.72922229 -0.17669396 -1.12095590 -0.86523850 -0.04031273 

注意:春季 (MAM) 和夏季 (JJA) 由于严格的字母排序而被切换。

第三:换回来

foo <- MEAN
for(i in 1:length(MEAN)) {
    if (mod (i,4) == 2) {
        foo[i+1] <- foo[i]    #switch 2nd 3rd row (JJA <-> MAM)
        foo[i] <- MEAN[i+1]
    }
}
# and generate new names for the array
d <- data.frame(date=seq(from=as.Date("1901-01-01"), to=as.Date("2009-12-31"), by="+3 month"))
d$seas <- mkseas(d,"DJF") 
d$seasyear <- paste(format(d[,1],"%Y"), d$seas ,sep="")
names(foo)<-d$seasyear  # add right order colnames
MEAN <-foo

最后,这会产生季节性均值的时间序列。好吧,我觉得它太复杂了,我想周围有更简单的解决方案。

此外,这个解决方案对于冬季 DJF 也有一个非常大的问题:到目前为止,12 月还没有从前一年中选择。这很容易解决(我猜),但使给定的方式更加复杂。

我真的希望周围有更好的想法!

4

4 回答 4

4

我这是你想要的?

# # create some data: daily values for three years
df <- data.frame(date = seq(from = as.Date("2007-01-01"),
                            to = as.Date("2009-12-31"),
                            by = "day"))
df$vals <- rnorm(nrow(df))

# add year
df$year <- format(df$date, "%Y")

# add season
df$seas <- mkseas(x = df, width = "DJF")

# calculate mean per season within each year
df2 <- aggregate(vals ~ seas + year, data = df, mean)

df2
#    seas year         vals
# 1   DJF 2007 -0.048407610
# 2   MAM 2007  0.086996842
# 3   JJA 2007  0.013864555
# 4   SON 2007 -0.081323367
# 5   DJF 2008  0.170887946
# 6   MAM 2008  0.147830260
# 7   JJA 2008  0.003008866
# 8   SON 2008 -0.057974215
# 9   DJF 2009 -0.043437437
# 10  MAM 2009 -0.048345979
# 11  JJA 2009  0.023860506
# 12  SON 2009 -0.060076870

因为mkseas将日期转换为具有所需顺序的级别的季节性因素,所以在按年份和季节进行聚合之后,顺序也是正确的。

于 2013-09-24T20:15:28.037 回答
2

如果您使用数字而不是字符串来表示月份和季节,这可能会更容易,至少一开始是这样。您可以通过简单的算术操作获得您想要的季节,包括将 12 月作为下一年的一部分。

pdsi <- data.frame(date = seq(
            from=as.Date("1901-01-01"), 
            to=as.Date("2009-12-31"), 
            by="day"))
pdsi$scPDSI <- rnorm(nrow(pdsi),  mean=1, sd=1)
pdsi$mon<-mon(pdsi$date)+1
pdsi$seas<-floor((pdsi$mon %% 12)/3)+1
pdsi$year<-year(pdsi$date)+1900
pdsi$syear<-pdsi$year
pdsi$syear[pdsi$mon==12]<-pdsi$syear[pdsi$mon==12]+1

要计算季节性平均值,您可以简单地执行以下操作:

meanArray<-tapply(pdsi$scPDSI,list(year=pdsi$syear,seas=pdsi$seas),mean)

现在你有

>head(meanArray)
      seas
year           1         2         3         4
  1901 1.0779676 1.0258306 1.1515175 0.9682434
  1902 0.9900312 0.8964994 1.1028336 1.0074296
  1903 0.9912233 0.9858088 1.1346901 1.0569518
  1904 0.7933653 1.1566892 1.1223454 0.8914211
  1905 1.1441863 1.1824074 0.9044940 0.8971485
  1906 0.9900826 0.9933909 0.9185972 0.8922987

如果您希望它作为一个平面数组,并具有适当的名称,则首先进行转置,然后将数组展平,并添加名称

colnames(meanArray)<-c("DJF","MAM","JJA","SON")
meanArray<-t(meanArray)
MEAN<-array(meanArray)
names(MEAN)<-paste(colnames(meanArray)[col(meanArray)],rownames(meanArray)[row(meanArray)],sep="")

这会让你得到你想要的结果

> head(MEAN)
  1901DJF   1901MAM   1901JJA   1901SON   1902DJF   1902MAM 
1.0779676 1.0258306 1.1515175 0.9682434 0.9900312 0.8964994  
于 2013-09-24T12:34:25.480 回答
1

如前所述,可以有非常简单的解决方案(也在此处发布)。我会结合使用zooseas包按季节聚合,看起来像这样:

library(zoo); library(seas)

seasTS <- aggregate(dataTS, mkseas(x=time(dataTS),width="DJF"), sum)

要为每年执行此操作,只需按年循环 mkseas()。请给我加点语法糖的咖啡。

干杯,

亚当

于 2015-09-18T18:44:59.907 回答
0

我遇到了同样的问题,但有月度数据,并且aggregate多年来不允许 DJF 拆分。为了解决这个问题,您可以添加一个合成年份列,将 12 月的值分配给下一年。

library(dplyr)
library(seas)
library(lubridate)

df <- data.frame(yearmonth = c("187601", "187602", "187603", "187604", "187605", "187606", "187607","187608", "187609", "187610", "187611", "187612", "187701", "187702", "187703", "187704", "187705", "187706", "187707", "187708", "187709", "187710", "187711", "187712", "187801", "187802", "187803", "187804", "187805", "187806", "187807", "187808", "187809", "187810", "187811", "187812", "187901", "187902", "187903", "187904", "187905", "187906", "187907", "187908", "187909", "187910", "187911", "187912"), 
                 SOI = rnorm(n = 48, mean = 0, sd = 4))


df %>% 
  mutate(yearmonth = lubridate::ymd(yearmonth, truncated = 1),
         year = year(yearmonth),
         month = month(yearmonth),
         seas = mkseas(yearmonth, width = "DJF"),
         year2 = ifelse(test = month == 12,
                        yes = year + 1,
                        no = year)) %>% 
  group_by(year2, seas) %>% 
  summarise(meanSOI = mean(SOI))
于 2021-02-05T03:43:38.327 回答