How to extract each year from a time-series data set in R

Viewed 588

I have a time-series data set EuStockMarket. It contains observations for four stock markets from 1991 to 1998. I would like to extract each year separately.

data(EuStockMarkets)
str(EuStockMarkets)
3 Answers

try this, using tsibble package:

library(tsibble)

tsbl <- as_tsibble(EuStockMarkets)

tsbl %>%
  group_by_key() %>%
  index_by(year = ~ year(.))

# A tsibble: 7,440 x 4 [1s] <UTC>
# Key:       key [4]
# Groups:    key @ year [32]
   index               key   value  year
   <dttm>              <chr> <dbl> <dbl>
 1 1991-07-01 02:18:33 DAX   1629.  1991
 2 1991-07-02 12:00:00 DAX   1614.  1991
 3 1991-07-03 21:41:27 DAX   1607.  1991
 4 1991-07-05 07:22:55 DAX   1621.  1991
 5 1991-07-06 17:04:22 DAX   1618.  1991
 6 1991-07-08 02:46:21 DAX   1611.  1991
 7 1991-07-09 12:27:49 DAX   1631.  1991
 8 1991-07-10 22:09:16 DAX   1640.  1991
 9 1991-07-12 07:50:44 DAX   1635.  1991
10 1991-07-13 17:32:11 DAX   1646.  1991
# ... with 7,430 more rows

The input, EuStockMarkets, in the question is a ts object so we assume the question is looking for a list of ts objects with one component per year. We provide the following solutions. In each case the years are used as the names of the components of the list.

1) zoo

Convert from ts to zoo class so that we can use split.zoo, split by year (the integer part of the time is the year) and convert back to ts. (If a list of zoo objects is ok then omit the lapply.)

library(zoo)
lapply(split(as.zoo(EuStockMarkets), as.integer(time(EuStockMarkets))), as.ts)

2) base

This solution is not as compact as (1) but if you need to avoid package dependencies it does not use any. It first splits the time vector into years and then for each component uses window to extract the sub-series for that year giving a list of ts objects.

spl <- split(time(EuStockMarkets), as.integer(time(EuStockMarkets)))
Map(window, start = Map(min, spl), end = Map(max, spl), list(EuStockMarkets))

Option 1

You can split the matrix-like ts object and reconstruct time series of each year by Map(). The final output is a list containing ts objects from 1991 to 1998. You can use the $ symbol to extract each year.

tm <- time(EuStockMarkets)
res1 <- Map(ts, split(as.data.frame(EuStockMarkets), floor(tm)),
            tm[c(T, cycle(EuStockMarkets)[-1] == 1)],
            frequency = frequency(EuStockMarkets))

Option 2

Another solution without splitting data, which may slightly improve efficiency.

cyc <- cycle(EuStockMarkets)[-1] ; tm <- time(EuStockMarkets)
res2 <- Map(window, list(EuStockMarkets), tm[c(T, cyc == 1)], tm[c(cyc == 1, T)])
names(res2) <- sapply(res2, start)[1, ]

Output

res1$`1991`

# Time Series:
# Start = c(1991, 130) 
# End = c(1991, 260) 
# Frequency = 260 
#              DAX    SMI    CAC   FTSE
# 1991.496 1628.75 1678.1 1772.8 2443.6
# 1991.500 1613.63 1688.5 1750.5 2460.2
# 1991.504 1606.51 1678.6 1718.0 2448.2
# etc.

res1$`1998`

# Time Series:
# Start = c(1998, 1) 
# End = c(1998, 169) 
# Frequency = 260 
#              DAX    SMI    CAC   FTSE
# 1998.000 4132.79 6044.7 2858.1 5049.8
# 1998.004 4132.79 6046.7 2874.1 5013.9
# 1998.008 4132.79 6046.7 2874.1 5013.9
# etc.
Related