Transforming a time-series into a data frame and back

19,841

Solution 1

Here are two ways. The first way creates dimnames for the matrix about to be created and then strings out the data into a matrix, transposes it and converts it to data frame. The second way creates a by list consisting of year and month variables and uses tapply on that later converting to data frame and adding names.

# create test data
set.seed(123)
tt <- ts(rnorm(12*5, 17, 8), start=c(1981,1), frequency = 12)

1) matrix. This solution requires that we have whole consecutive years

dmn <- list(month.abb, unique(floor(time(tt))))
as.data.frame(t(matrix(tt, 12, dimnames = dmn)))

If we don't care about the nice names it is just as.data.frame(t(matrix(tt, 12))) .

We could replace the dmn<- line with the following simpler line using @thelatemail's comment:

dmn <- dimnames(.preformat.ts(tt))

2) tapply. A more general solution using tapply is the following:

Month <-  factor(cycle(tt), levels = 1:12, labels = month.abb)
tapply(tt, list(year = floor(time(tt)), month = Month), c)

Note: To invert this suppose X is any of the solutions above. Then try:

ts(c(t(X)), start = 1981, freq = 12)

Update

Improvement motivated by comments of @latemail below.

Solution 2

Example with the AirPassengers dataset:

Make the data available and check its type:

data(AirPassengers)
class(AirPassengers)

Convert Time-Series into a data frame:

df <- data.frame(AirPassengers, year = trunc(time(AirPassengers)), 
month = month.abb[cycle(AirPassengers)])

Redo the creation of the Time-Series object:

tsData = ts(df$AirPassengers, start = c(1949,1), end = c(1960,12), frequency = 12)

Plot the results to ensure correct execution:

components.ts = decompose(tsData)
plot(components.ts)

Solution 3

Try the package "tsbox"

ts = ts(rnorm(12*5, 17, 8), start=c(1981,1), frequency = 12) df = ts_df(ts) str(df)

data.frame: 60 obs. of 2 variables: time : Date, format: "1981-01-01" "1981-02-01" value: num 23.15 22.77 5.1 1.05 13.87

Share:
19,841
Roland Kofler
Author by

Roland Kofler

Updated on June 18, 2022

Comments

  • Roland Kofler
    Roland Kofler almost 2 years

    The output of a time-series looks like a data frame:

    ts(rnorm(12*5, 17, 8), start=c(1981,1), frequency = 12)
    
           Jan       Feb       Mar       Apr       May       Jun       Jul     ...
    1981 14.064085 21.664250 14.800249 -5.773095 16.477470  1.129674 16.747669 ...
    1982 23.973620 17.851890 21.387944 28.451552 24.177141 25.212271 19.123179 ...
    1983 19.801210 11.523906  8.103132  9.382778  4.614325 21.751529  9.540851 ...
    1984 15.394517 21.021790 23.115453 12.685093 -2.209352 28.318686 10.159940 ...
    1985 20.708447 13.095117 32.815273  9.393895 19.551045 24.847337 18.703991 ...
    

    It would be handy to transform it into a data frame with columns Jan, Feb, Mar... and rows 1981, 1982, ... and then back. What's the most elegant way to do this?