我有一個時間序列,我想將它轉換為一個資料框,其中包含包含值的列和一個帶有 ttime 的 Date/POSIXct 列。可重現的例子:
data_ts <- ts(matrix(1:14, ncol= 2), start= c(2000, 1), frequency= 6)
預期輸出為:
data_df <- data.frame(Series_1= 1:7, Series_2= 8:14, Date= seq(as.Date("2000/1/1"), length.out= nrow(data_ts)*2, by= "month")[seq(1, nrow(data_ts)*2, 2)])
data_df
Series_1 Series_2 Date
1 1 8 2000-01-01
2 2 9 2000-03-01
3 3 10 2000-05-01
4 4 11 2000-07-01
5 5 12 2000-09-01
6 6 13 2000-11-01
7 7 14 2001-01-01
在這個例子中frequencyis6和 start 是 atc(2000, 1)但在我的用例中我事先不知道這些引數。事實上,thefrequency也可能很大,以至于我指的是小時/分鐘或秒(frequency= 365*24*60*60例如)。如果頻率以年/月/周/天Date為單位就足夠了,但對于小時/分鐘/秒,列必須更改,當然(到POSIXct)。所以我正在嘗試一個通用的解決方案。我希望它是基礎 R。
有一個類似的問題,但答案有一列日期為十進制數。相反,我需要一個實際的 Date/PSIXct 列。
uj5u.com熱心網友回復:
我想出了一種方法,seq如果頻率是完整的月、周或天,則使用該函式,選擇相應的by引數 ( "month","week"或"day")。對于頻率不是完整的月、周或日的情況,我計算了頻率對應的秒數。例如,頻率為365*24意味著我們需要進入60*60=3600第二步(因為365*24意味著小時和60*60第二步是小時步),依此類推。
這一切都提供了以下相當長的解決方案,但它適用于我迄今為止嘗試過的所有情況:
ts_to_df <- function(data){
ts_freq <- frequency(data)
# Works for univariate and multivariate time series:
if(is.null(dim(data))){
ts_length <- length(data)
} else{
ts_length <- nrow(data)
}
# For full month.
if(ts_freq %in% c(1, 2, 3, 4, 6, 12)){
n_months <- 12/ ts_freq
first_month <- as.Date(paste(start(data)[1],
start(data)[2]*n_months-(n_months-1), "1", sep= "/"))
ts_date <- seq(first_month, length.out= ts_length*n_months, by= "month")
ts_date <- ts_date[seq(1, length(ts_date), by= n_months)]
# For full weeks.
} else if(ts_freq == 52){
first_week <- seq(as.Date(paste(start(data)[1], "/1/1", sep="")), length.out= start(data)[2], by= "week")[start(data)[2]]
ts_date <- seq(first_week, length.out= ts_length, by= "week")
# For full days.
} else if(ts_freq == 365 | ts_freq == 366){
first_day <- as.Date(paste(start(data)[1], "/1/", start(data)[2], sep=""))
ts_date <- seq(first_day, length.out= ts_length, by= "day")
# All other cases.
} else{
sec_year <- 365*24*60*60
freq_fraction <- 1/ts_freq
sec_steps <- sec_year*freq_fraction
first_sec <- as.POSIXct(paste(start(data)[1], "-01-01 00:00:01", sep="")) sec_steps*start(data)[2] - sec_steps
ts_date <- first_sec sec_steps *0:(ts_length-1)
}
# Make a data.frame.
data_df <- data.frame(as.matrix(data))
data_df$date <- ts_date
data_df
}
將函式應用于 ats以周為頻率:
ts_to_df(ts(matrix(1:14, ncol= 2), start= c(2000, 1), frequency= 52))
Series.1 Series.2 date
1 1 8 2000-01-01
2 2 9 2000-01-08
3 3 10 2000-01-15
4 4 11 2000-01-22
5 5 12 2000-01-29
6 6 13 2000-02-05
7 7 14 2000-02-12
現在以ts分鐘為頻率并從 2009 年的第 10 分鐘開始:
ts_to_df(ts(matrix(1:14, ncol= 2), start= c(2009, 10), frequency= 365*24*60))
Series.1 Series.2 date
1 1 8 2009-01-01 00:09:01
2 2 9 2009-01-01 00:10:01
3 3 10 2009-01-01 00:11:01
4 4 11 2009-01-01 00:12:01
5 5 12 2009-01-01 00:13:01
6 6 13 2009-01-01 00:14:01
7 7 14 2009-01-01 00:15:01
等等...
uj5u.com熱心網友回復:
我認為最簡單的方法是使用 tsbox 和 base R data.frames。
library(tsbox)
data_ts = ts(matrix(1:14, ncol= 2), start= c(2000, 1), frequency= 6)
ts_df = ts_df(data_ts)
ts_df = dcast(ts_df, time~id, value.var=value)
輸出:
> ts_dt
time Series 1 Series 2
1: 2000-01-01 1 8
2: 2000-03-01 2 9
3: 2000-05-01 3 10
4: 2000-07-01 4 11
5: 2000-09-01 5 12
6: 2000-11-01 6 13
7: 2001-01-01 7 14
如果您只使用基本 RI,不知道一個非常方便的解決方案,但是在這個社區中有比我更好的 R 編碼器,也許有人知道一個沒有幾十行的解決方案。
更新:
僅使用基礎 R 的嘗試。如果有幾個月:
data_ts = ts(matrix(1:14, ncol= 2), start= c(2000, 1), frequency= 6)
df_ts = data.frame(data_ts)
df_ts$date = as.numeric(time(data_ts))
df_ts$date = as.Date(paste0(floor(df_ts$date), "-",
sprintf("d", 1 round((df_ts$date-floor(df_ts$date))*12)), "-01"))
輸出:
> df_ts
Series.1 Series.2 date
1 1 8 2000-01-01
2 2 9 2000-03-01
3 3 10 2000-05-01
4 4 11 2000-07-01
5 5 12 2000-09-01
6 6 13 2000-11-01
7 7 14 2001-01-01
如果有幾周:
df_ts = data.frame(data_ts)
df_ts$week = as.numeric(time(data_ts))
df_ts$week = paste0(floor(df_ts$week), "-",
sprintf("d", 1 round((df_ts$week-floor(df_ts$week))*52)))
輸出:
Series.1 Series.2 week
1 1 15 2000-01
2 2 16 2000-02
3 3 17 2000-03
4 4 18 2000-04
5 5 19 2000-05
6 6 20 2000-06
7 7 21 2000-07
8 8 22 2000-08
9 9 23 2000-09
10 10 24 2000-10
11 11 25 2000-11
12 12 26 2000-12
13 13 27 2000-13
14 14 28 2000-14
如果有幾天:
data_ts = ts(matrix(1:20, ncol= 2), start= c(2000, 1, 1), frequency= 365)
df_ts = data.frame(data_ts)
df_ts$date = time(data_ts)
df_ts$date = as.Date(paste0(floor(df_ts$date),
"-",
sprintf("d", 1 round((df_ts$date-floor(df_ts$date))*365)),
"-01"), "%Y-%j")
輸出:
> df_ts
Series.1 Series.2 date
1 1 11 2000-01-01
2 2 12 2000-01-02
3 3 13 2000-01-03
4 4 14 2000-01-04
5 5 15 2000-01-05
6 6 16 2000-01-06
7 7 17 2000-01-07
8 8 18 2000-01-08
9 9 19 2000-01-09
10 10 20 2000-01-10
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/387562.html
