Roland Kofler - 1 year ago 85
R Question

# transforming a ts in a data.frame and back

The output of a ts 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 if it is easy to transform it into such a data.frame with colums Jan, Feb, Mar... and rows 1981, 1982, ... and then back.
What's the most elegant solution to do it?

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)))` .

2) tapply. A more general solution using `tapply` is:

``````tapply(tt, list(year = floor(time(tt)), month = month.abb[cycle(tt)]), c)
``````

If we don't care about names we can replace `month.abb[cycle(tt)]` with just `cycle(tt)`.

Note: To invert this suppose `DF` is any of the data frame solutions above. Then try:

``````ts(c(t(DF)), start = 1981, freq = 12)
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download