简体   繁体   中英

Transforming a time-series into a data frame and back

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?

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.

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)

试试“ 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM