将R中的每日“data.frame”转换为“ts”

4

我有一个名为“rates”的数据集,其内容如下:

       Date  Price
1 2012-11-01 6.2411
2 2012-11-02 6.2415
3 2012-11-05 6.2454
4 2012-11-06 6.2456
5 2012-11-07 6.2437
6 2012-11-08 6.2429

> class(rate)
[1] "data.frame"

使用 R 代码将此数据集转换为时间序列数据:

rate<-ts(data = rate, start =1, freq=1)
> class(rate)
[1] "mts"    "ts"     "matrix"

> head(rate)
     Date  Price
[1,] 15645 6.2411
[2,] 15646 6.2415
[3,] 15649 6.2454
[4,] 15650 6.2456
[5,] 15651 6.2437
[6,] 15652 6.2429

如您所见,日期被转换为数字。因此,我使用as.date()函数:

rate[,1] <- as.Date(rate[,1],origin = "1899-12-30")
> head(rate)
       Date  Price
[1,] -719162 6.2411
[2,] -718797 6.2415
[3,] -718432 6.2454
[4,] -718067 6.2456
[5,] -717701 6.2437
[6,] -717336 6.2429

有人可以帮我解决这个问题吗?谢谢。

可以使用xts包,即 library(xts); xts(Date = rate[,1], order.by = as.Date(rate[,1])) - akrun
请记得在将来使用 dput() 共享您的数据。 - Hack-R
在许多情况下,日期数据最好从分析中排除。 "日期"数据只是标签,没有其他意义。如果其他人使用其他标签(不同的日期),只要其他变量的数据相同,在分析后他们将得到相同的结果。特别是在这些不规则日期的数据中,将日期列指定为您正在使用的数据框的行名称非常有用。否则(如果您保留数据框中的日期列),每当进行关键操作时都应将其排除。例如,分析日期列是否稳定是没有意义的。 - Erdogan CEVHER
别忘了通过点击下投票按钮下面的灰色勾号来接受最佳答案。 - acylam
2个回答

2
你的代码问题在于,在将整个数据框强制转换为时间序列矩阵之后,你试图将日期列转换为日期类型。正确的方法是先将“日期”列转换为日期类型,计算从起始年份(2012年)开始每日增量的起始日期,然后使用该信息将“价格”列转换为时间序列。
# Here is your data in "dput" form
rate = structure(list(Date = c("2012-11-01", "2012-11-02", "2012-11-05", 
                           "2012-11-06", "2012-11-07", "2012-11-08"), 
                  Price = c(6.2411, 6.2415, 6.2454, 6.2456, 6.2437, 6.2429)), 
             .Names = c("Date", "Price"), class = "data.frame", row.names = c(NA, -6L))

# Convert Date column to type "Date"
rate$Date = as.Date(rate$Date, format = "%Y-%m-%d")

# Convert "11-01" to day of the year 
dayOfYear = as.numeric(format(rate[1,1], "%j"))

# Use 2012 and dayOfYear as starting date
rate_ts = ts(rate$Price, start = c(2012, dayOfYear), frequency = 365)

> class(rate_ts)
[1] "ts"

> rate_ts
Time Series:
Start = c(2012, 306) 
End = c(2012, 311) 
Frequency = 365 
[1] 6.2411 6.2415 6.2454 6.2456 6.2437 6.2429

这里,"%j" 只是告诉 format.Date 函数将 Date 的第一个元素(2012-11-01)转换为当年的第几天。
我还想指出,由于您的时间序列是每日的,所以应该使用 frequency = 365 而不是 frequency = 1
绘图:
# Plot time series without x-axis
plot(rate_ts, ylab = "Price", xaxt = "n")

# Extract first and last date value of rate_ts
tsp = attributes(rate_ts)$tsp

# Plot x-axis
axis(1, at = seq(tsp[1], tsp[2], along = rate_ts), 
     labels = format(rate$Date, "%Y-%m-%d"))

这最后一行允许你通过改变format()的第二个参数来自定义x轴格式。而at =参数则允许你指定刻度。

enter image description here

感谢Jake Burkhead在this answer中提供的绘图方法。

ts 数据是每日的,但是不规则的每日。我的解决方案对于除了经典的“周末数据缺失”之外的任何不规则性都很强大。 - Erdogan CEVHER
@ErdoganCEVHER Op只是要求将他的数据框转换为时间序列对象的方法。我提供了解决方案并指出了他错误的可能原因。另一方面,您的回答中没有提供任何代码来解决op的问题。在op要求简单转换时谈论鲁棒性似乎与主题无关。此外,虽然ts()会自动强制转换他的ts,但默认设置并不意味着它正确地强制转换。而您也没有说明应该如何做。 - acylam
OP在R的函数中执行强制操作时没有必要使用ts()。例如,假设OP将对其时间序列执行平稳性分析。然后,library(fUnitRoots); unitrootTest(df[,1])会自动执行该任务。强制转换是通过R函数unitrootTest内部实现的。我的意思是有许多R函数可以处理自动强制转换。这就是为什么OP几乎不需要关心类转换的原因。即使没有对df[,1]进行任何处理,他也可以执行非常复杂的操作。 - Erdogan CEVHER
谢谢您的帮助,但仍然存在问题。按照您的步骤,在“rate$Price = ts(rate$Price, start = c(2012, dayOfYear), frequency = 365)”之后,“class(rate)”仍然是“data.frame”。如果我使用“rate= ts(data=rate, start = c(2012, dayOfYear), frequency = 365)”,结果将与我在问题中得到的相同。请再次检查一下,好吗? - Yanyan
@useR 是的,我现在明白了。谢谢你。我之前问日期的类是因为我想在x轴上绘制这些日期。通过使用您提供的步骤,x轴上的内容变成了数字,100、200等等。 - Yanyan
显示剩余4条评论

0
df <- data.frame(c(6.2411, 6.2415, 6.2454, 6.2456, 6.2437, 6.2429))
names(df) <- "price"
rownames(df) <- c("2012-11-01", "2012-11-02", "2012-11-05", "2012-11-06", "2012-11-07", "2012-11-08")
df
#            price
# 2012-11-01 6.2411
# 2012-11-02 6.2415
# 2012-11-05 6.2454
# 2012-11-06 6.2456
# 2012-11-07 6.2437
# 2012-11-08 6.2429

你正在尝试分配不规则的日期。因此,`lubridate`可能不能解决你的问题。当你使用`df[,1]`进行需要`ts`对象的进一步操作时,`df[,1]`将自动转换为这个类别。你可以对`df[,1]`进行任何分析。
请注意: 观察点是非等距(不均匀/不规则)间隔的(例如国定假日可能导致观察数量的差异)。当考虑多个系列以及价格时,你可能会遇到交叉点。在这种情况下,你应该忽略不规则性的影响,因为对于许多观察来说,观察的间距将是相同的,并且不会如此高度不规则。此外,还要考虑到使用线性插值将数据转换为等间距观察可能引入一些重大且难以量化的偏差(参见:Scholes和Williams)。

M. Scholes和J. Williams,“从非同步数据中估算贝塔”,《金融经济学杂志》5:309-327,1977年。

关于Excel2016的概括:
假设您在Excel文件(DatePrice.xlsx)中有数千个日期和价格数据:

   A   B    
1 Date Price    
2 2012-11-01 6.2411
3 2012-11-02 6.2415
...

接下来,执行以下操作:

library(readxl)
# Use the path returned from getwd() function that is R's working directory
df <- as.data.frame(read_excel("C://Users//User//Documents//Revolution//DatePrice.xlsx"))
names(df) <- c("date","price")
rownames(df) <- df[,1]
df[,1] <- NULL
df

再次强调,df[,1]将是在任何进一步分析中用于强制操作的时间序列。例如;

如何继续解决方案的示例分析:

price <- df[,1]
plot(ts(price)); abline(a=mean(ts(price)), b=0) # graphically, price~ I(1)

#Stationarity analysis (even with 6 obs, it produces results!)
library(fUnitRoots); unitrootTest(price) # formally, price~ I(1)  p=0.6889

plot(diff(ts(price), differences=1)) # graphically, Delta(price) ~ I(0)
unitrootTest(diff(ts(price), differences=1)) # formally, Delta(price) ~ I(0) p=1e-04<0.05

你展示的方式中,df[,1] 只是日期列,不是时间序列。即使你想表达的是 df[,2],在 R 中它仍然 不是 "Time-Series" 类型。从你的代码来看,价格列只是 "numeric"。请检查 class(df[,2]) - acylam
在两种解决方案(非Excel,Excel)中,df [,1]是价格系列,而不是日期列。您在非Excel解决方案中缺少“行分配日期并仅使用价格系列”,并且在Excel解决方案中缺少“df [,1] <- NULL”分配。在这两种解决方案中,class(df [,1])为“numeric”。但这与他处理的问题类型无关。请参见library(fUnitRoots); unitrootTest(df [,1])。没有需要ts()! OP的问题特别之处在于它使用不规则日期。对于这种类型的问题,上面的解决方案非常实用。 - Erdogan CEVHER
我想知道那个点踩的人是否真正理解我的回答范围是什么... - Erdogan CEVHER

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接