如何按时间序列绘制20年的每日数据


9

我有以下数据集:https : //dl.dropbox.com/u/22681355/ORACLE.csv, 并想按“日期”在“打开”中绘制每日变化,所以我做了以下工作:

oracle <- read.csv(file="http://dl.dropbox.com/u/22681355/ORACLE.csv", header=TRUE)
plot(oracle$Date, oracle$Open, type="l")

我得到以下信息:

在此处输入图片说明

现在这显然不是有史以来最好的图,所以我想知道在绘制这样的详细数据时使用什么正确的方法?


1
情节实际上还不是很糟糕。...但是如何改善它取决于您要强调的内容。您是否只想绘制每周数据?是否要添加平滑线?你应该改变x轴的标签,当然....
彼得·弗洛姆

是的,我希望有一条平滑的线,例如:dl.dropbox.com/u/22681355/Untitled.tiff,如果比例尺以年为单位也可以,但平滑的线将是必不可少的。我试图将类型更改为“ l”,但实际上并没有执行任何操作。
dbr 2012年

R一个方式来增加线条流畅的loess。我正在出门,但是尝试在R中黄土,如果您遇到问题,请编辑帖子,然后肯定会有人能够为您提供帮助。也有其他平滑方法,但我认为黄土是一个很好的默认方法。
彼得·富勒姆

Answers:


8

数据的问题并不在于它是否非常详细:周末没有任何值,这就是为什么要用差距绘制的原因。有两种处理方法:

  1. 无论是尝试猜测近似值在周末与一些平滑方法(smooth.splineloess等)。简单插补的代码如下。但是在这种情况下,您将为数据引入“非自然”和人为的内容。这就是为什么我更喜欢第二种选择。
currentDate <- min(as.Date(oracle$Date))
dates <- c(currentDate)
openValues <- c(oracle$Open[5045])
i <- 5044
while (i > 0) {
  currentDate <- currentDate + 1;
  dates <- c(dates, currentDate)
  if (currentDate == as.Date(oracle$Date[i])) {
        # just copy value and move
        openValues <- c(openValues, oracle$Open[i])
        i <- i-1
      } else {
        # interpolate value
        openValues <- c(openValues, mean(oracle$Open[i:i-1]))
  }
}
plot(dates, openValues, type="l")
  1. 您可以从每天一次到每周一次,只需平均(例如)五个连续的点数即可累积到一个星期(在这种情况下,您正在“杀死”某些信息)。只是一个简单的例子
openValues = c(mean(oracle$Open[1:5]));
dates = c(as.Date(oracle$Date[1]));
for (i in seq(6,5045,5)) {
  openValues = c(openValues, mean(oracle$Open[i:i+5]));
      dates = c(dates, as.Date(oracle$Date[i]));
}
plot(dates, openValues, type="l")

希望它会有所帮助。


1
谢谢,这真的很有帮助。问题在于,由于这是库存数据,因此从每日到每周转换肯定可以“杀死”一些关键数据。有什么办法可以使白天的线条流畅,而周末没有空白?
dbr 2012年

好的,如果您不求平均对您很重要,那么我已经更新了答案,提供了对周末进行插值的示例代码。
德米特里·拉普捷夫

@dbr顺便说一句,如果您想依靠R进行插值,那将非常简单:plot(as.Date(oracle$Date), oracle$Open, type='l')
Dmitry Laptev 2012年

1
如果您只是想在周末休息一下openValues <- c(openValues, mean(oracle$Open[i:i-1])),可将第一种方法的行替换为openValues <- c(openValues, NA)
Dmitry Laptev

9

因为该问题是许多统计软件环境所共有的,所以让我们在“ 交叉验证”中进行讨论,而不是将其迁移到R特定的论坛(例如StackOverflow)。

真正的问题是,Date作为一个治疗因子 --a离散变量-这样的线没有被正确连接。 (也没有在水平方向上精确地绘制点。)

情节比较

为了进行右侧绘图,将该Date字段从一个因子转换为实际日期,并通过简单的计算(在周六和周日之间中断几周)来确定每周,并在周末通过循环遍历这些行来中断这些行:

oracle$date <- as.Date(oracle$Date)
oracle$week.num <- (as.integer(oracle$date) + 3) %/% 7 
oracle$week <- as.Date(oracle$week.num * 7 - 3, as.Date("1970-01-01", "%Y-%m-%d"))

par(mfrow=c(1,2))
plot(as.factor(unclass(oracle$Date[1:120])), oracle$Open[1:120], type="l",
     main="Original Plot: Inset", xlab="Factor code")
plot(oracle$date[1:120], oracle$Open[1:120], type="n", ylab="Price", 
     main="Oracle Opening Prices")
tmp <- by(oracle[1:120,], oracle$week[1:120], function(x) lines(x$date, x$Open, lwd=2))

(由于每个星期的等效日期,也就是该星期的星期一,也存储在oracle数据框中,因为它对于绘制每周汇总数据很有用。)

通过模拟最后一行以显示所有数据,可以简单地实现最初的意图。要添加有关季节性行为的一些信息,以下图表在每个日历年中按周改变颜色:

par(mfrow=c(1,1))
colors <- terrain.colors(52)
plot(oracle$date, oracle$Open, type="n", main="Oracle Opening Prices")
tmp <- by(oracle, oracle$week, 
          function(x) lines(x$date, x$Open, col=colors[x$week.num %% 52 + 1]))

最终情节


不是财务人员,但我喜欢季节性趋势技巧。
约翰·罗伯逊

@John最初添加颜色只是为了帮助眼睛。但是看了一下结果,我发现有趣的是,在2000年互联网股票爆炸之前的六年中,橙色周(大约是夏末)都呈现出强劲的上升趋势。此后,这种趋势似乎消失了。
ub

我也注意到了这一点,并且想知道是什么关系。
约翰·罗伯逊

whuber和@John Robertson-可能并不太紧密,但是1998年也是Microsoft迁移到Sql Server 7.0 / Sql Server 2000的现代代码库的时候,到2000年,他们为Oracle提供了更强大的竞争:en.wikipedia.org/wiki/ Microsoft_SQL_Server#Genesis
Rob

1
@安德烈,我会写“日期”。如果是相对日期,那么(在空间允许的情况下)我会写“ 1990年1月1日以来的年份”之类的内容。在该示例中,我希望很明显只有复数的“年”可以使用。顺便说一句,通常我会使用相对日期(与时间相关的数据)来分析与时间相关的数据(以确保数值稳定性,易于阅读统计摘要等),但会将它们转换回实际日期以进行图形显示(因为显示应使用有意义的,可解释的度量单位) 。
ub

1

我不会在周末插值。周六很少有证券交易所交易,而周日我不知道。您正在为不存在的数据引入一个估计,那么为什么不从数据集中删除星期六和星期日呢?我会做类似下面的事情:

require(ggplot2)
require(scales)
require(gridExtra)
require(lubridate)
require(reshape)

set.seed(12345)

# Create data frame from random data
daysback <- 1000 # number of days, only a few for this example
startdate <- as.Date(format(now()), format = "%Y-%m-%d") - days(daysback)
mydf <- data.frame(mydate = seq(as.Date(startdate), by = "day", length.out = daysback),
                   open = runif(daysback, min = 600, max = 800))

# Now that we have a data frame, remove the weekend days
mydf <- mydf[!(weekdays(as.Date(mydf$mydate)) %in% c('Saturday','Sunday')),] # remove weekend days
    # Calculate change, except for the first date
    mydf$diff <- c(NA, diff(mydf$open))
    # Remove first row with no 'diff' value
    firstdate <- head(mydf$mydate, 1)
mydf <- mydf[mydf$mydate > firstdate, ]

p <- ggplot(mydf, aes(x = mydate, y = diff)) +
    geom_bar(data = mydf, stat = "identity", fill = "red")

print(p)

是的,这就是我想要得到的。但是通过在周末“跳过”只是在行之间留出空白是不是更简单的方法?
dbr 2012年

我认为R假定如果有日期,则可以使用它们,因此您应该删除不需要的日期。毕竟,这并不难,上面的代码大部分都是多余的,重要的一点是删除,只需要一行,即mydf <-mydf [!(weekdays(as.Date(mydf $ mydate))%in%c ('Saturday','Sunday')),]
SlowLearner 2012年

但已在数据集中删除,因此不包括星期六和星期日的日期
dbr 2012

啊。我可能完全误解了您的问题。如果您只是想平滑数据,那么我同意,黄土之类的方法可以解决,但那会改变数据。或者,您可以创建一个非常大的图来显示细节。例如,宽度为20,000像素左右。
SlowLearner 2012年

以及如何使用Dmitry的解决方案,而不是仅使用0来估算上一个和下一个值的平均值?
dbr 2012年

0

关于绘图的外观,我想在x轴下添加多个标签会在视觉上对其进行改善。建议的情节外观,您可以在这里http://imgur.com/ZTNPniA

我不知道如何绘制这样的图,这只是一个想法(我在R中还没有看到实现)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.