2009-07-25 33 views
17

我有一個數據框包含多個時間序列的返回,存儲在列中。整形時間系列數據從寬到高格式(繪圖)

第一列包含日期,隨後的列是獨立的時間序列,每個都有一個名稱。列標題是變量名稱。

## I have a data frame like this 
t <- seq(as.Date('2009-01-01'),by='days',length=10) 
X <- rnorm(10,0,1) 
Y <- rnorm(10,0,2) 
Z <- rnorm(10,0,4) 

dat <- data.frame(t,X,Y,Z) 

## which appears as 
      t   X   Y   Z 
1 2009-01-01 -1.8763317 -0.1885183 -6.655663 
2 2009-01-02 -1.3566227 -2.1851226 -3.863576 
3 2009-01-03 -1.3447188 2.4180249 -1.543931 

我想繪製每個時間系列作爲單獨的圖上的一條線,在一個格子中,每個圖由變量名標記。

繪製該格子的數據必須是一個高大的格式,因爲這樣的:

  t symbol  price 
1 2009-01-01  X -1.8763317 
2 2009-01-02  Y -0.1885183 
2 2009-01-02  Z -6.655663 

什麼是一個很好的函數調用來做到這一點?

回答

16

你也可以使用熔體()從「重塑」庫(我認爲這是更容易使用比重塑()本身) - 這會節省你不必回來添加時間列的額外步驟...

> library(reshape) 
> m <- melt(dat,id="t",variable_name="symbol") 
> names(m) <- sub("value","price",names(m)) 
> head(m) 
      t symbol  price 
1 2009-01-01  X -1.14945096 
2 2009-01-02  X -0.07619870 
3 2009-01-03  X 0.01547395 
4 2009-01-04  X -0.31493143 
5 2009-01-05  X 1.26985167 
6 2009-01-06  X 1.31492397 
> class(m$t) 
[1] "Date" 
> library(lattice)                
> xyplot(price ~ t | symbol, data=m ,type ="l", layout = c(1,3)) 

對於這個特殊的任務,不過,我會考慮使用「動物園」庫,這不會要求您重新整理數據幀:

> library(zoo)                 
> zobj <- zoo(dat[,-1],dat[,1])             
> plot(zobj,col=rainbow(ncol(zobj))) 

R開發者/貢獻者(Gabor和Hadley在這種情況下)爲我們提供了許多不錯的選擇。(也不能忘記Deepayan的格子包)

+0

融化正是我所期待的。史蒂芬,你可以編輯你的答案,包括最後的繪圖步驟? – medriscoll 2009-07-30 04:21:22

+1

浪費了一小時的「stats :: reshape()」功能,我不得不想知道某些編寫R函數的人正在服用哪些藥物。熔化()很棒。 (再次感謝哈德利) – forkandwait 2009-10-22 19:46:59

9

如果是多變量時間序列,請考慮使用相同名稱的包將其存儲爲動物園對象。這使得索引,合併,更容易 - 看動物園的小插曲。

但是當你問格子圖 - 這也可以做到。在這個例子中,我們構建了一個簡單的「長」與data.frame日期列,以及列,其值爲「VAL」和可變id列「變種」:

> set.seed(42) 
> D <- data.frame(date=rep(seq(as.Date("2009-01-01"),Sys.Date(),by="week"),2),\ 
        val=c(cumsum(rnorm(30)), cumsum(rnorm(30))), \ 
        var=c(rep("x1",30), rep("x2",30))) 

鑑於數據集,每個繪圖

> library(lattice) 
> xyplot(val ~ date | var, data=D, panel=panel.lines) 
3

對於在日期數據框「臨時」:你的描述由從格子包xyplot通過詢問「通過變量分組給定值數據」,我們在每個面板打開行的陰謀做第一列和每個其他列中的值:

> par(mfrow=c(3,4)) # 3x4 grid of plots 
> mapply(plot,temp[,-1],main=names(temp)[-1],MoreArgs=list(x=temp[,1],xlab="Date",type="l",ylab="Value")) 
2

非常感謝答案人 - 德克的回答是關於標記。

缺少的步驟竟然是使用「stack()」函數將數據幀從寬格式轉換爲長格式。我知道可能有更簡單的方法來使用reshape()函數來做到這一點,很高興看到一個例子,如果有人想要發佈它。

所以這裏就是我終於實現了,用在問題中提到的「逸」數據框:

## use stack() to reshape the data frame to a long format 
## <time> <stock> <price> 
stackdat <- stack(dat,select=-t) 
names(stackdat) <- c('price','symbol') 

## create a column of date & bind to the new data frame 
nsymbol <- length(levels(stackdat$symbol)) 
date <- rep(dat$t, nsymbol) 
newdat <- cbind(date,stackdat) 

## plot it with lattice 
library(lattice) 
xyplot(price ~ date | symbol, ## model conditions on 'symbol' to lattice 
     data=newdat,   ## data source 
     type='l',    ## line 
     layout=c(nsymbol,1)) ## put it on a single line 

## or plot it with ggplot2 
library(ggplot2) 
qplot(date, price, data = newdat, geom="line") + facet_grid(. ~ symbol) 
+2

參見從重塑包融轉換從廣角到長。 – hadley 2009-07-26 14:12:12

12

tidyr gather的幫助頁面:

例子

library(tidyr) 
library(dplyr) 
# From http://stackoverflow.com/questions/1181060 
stocks <- data.frame(
    time = as.Date('2009-01-01') + 0:9, 
    X = rnorm(10, 0, 1), 
    Y = rnorm(10, 0, 2), 
    Z = rnorm(10, 0, 4) 
) 

gather(stocks, stock, price, -time) 
stocks %>% gather(stock, price, -time)