ggplot2:从x轴日期

时间:2015-10-01 17:13:31

标签: r date ggplot2

在ggplot2中绘制库存数据时遇到问题,x轴包含周末和假日的间隙。 this帖子非常有帮助,但在尝试使用有序因素时遇到了各种各样的问题。

library(xts)
library(grid)
library(dplyr)
library(scales)
library(bdscale)
library(ggplot2)
library(quantmod)

getSymbols("SPY", from = Sys.Date() - 1460, to = Sys.Date(), adjust = TRUE, auto.assign = TRUE)

input <- data.frame(SPY["2015/"])
names(input) <- c("Open", "High", "Low", "Close", "Volume", "Adjusted")

# i've tried changing rownames() to index(), and the plot looks good, but the x-axis is inaccurate
# i've also tried as.factor()
xaxis <- as.Date(rownames(input)) 
input$xaxis <- xaxis

p <- ggplot(input)
p <- p + geom_segment(aes(x = xaxis, xend = xaxis, y = Low, yend = High), size = 0.50)           # body
p <- p + geom_segment(aes(x = xaxis - 0.4, xend = xaxis, y = Open, yend = Open), size = 0.90)    # open
p <- p + geom_segment(aes(x = xaxis, xend = xaxis + 0.4, y = Close, yend = Close), size = 0.90)  # close
p <- p + scale_y_continuous(scale_y_log10())
p + ggtitle("SPY: 2015")

enter image description here

上面的图表(没有红色框)是使用上面的代码段生成的。以下图表是尝试某些解决方案时的一些问题。首先,如果我尝试使用数据框的索引,我将生成一个漂亮的图形,但x轴是不准确的;该数据目前在10月份结束,但在下面的情节中,它将于7月结束: enter image description here

xaxis <- as.Date(index(input))

其次,如果我尝试将rownames强制转换为有序因子,我会丢失水平刻度数据(表示打开和关闭)。
enter image description here

xaxis <- factor(rownames(input), ordered = TRUE) 

如果我使用包bdscale,同样的问题是删除水平刻度,但网格线更清晰:

enter image description here

p <- p + scale_x_bd(business.dates = xaxis)

5 个答案:

答案 0 :(得分:2)

您可能需要将日期视为离散值而不是连续值。这种方法略微简化了代码版本,可能如下所示:

getSymbols("SPY", from = Sys.Date() - 1460, to = Sys.Date(), adjust = TRUE, auto.assign = TRUE)
SPY <- SPY["2015/"]
colnames(SPY) <- sub("SPY.","", colnames(SPY))
month_brks <- c(1,endpoints(SPY, "months")[-1])

p <- ggplot(data.frame(xaxis=seq(nrow(SPY)), SPY))
p <- p + geom_linerange(aes(x=xaxis, ymin=Low, ymax=High), size=.5)
p <- p + geom_text(aes(x = xaxis,  y = Open), size = 4., label="-", hjust=.7, vjust=0)  # Open
p <- p + geom_text(aes(x = xaxis,  y = Close), size = 4., label="-", hjust=-.1, vjust=0)  # close
p <- p + scale_x_continuous(breaks=month_brks, labels=format(index(SPY)[month_brks], "%d %b %Y"))
p <- p + labs(title="SPY: 2015", x="Date", y="Price")

更新

更新了轴标签的处理。

答案 1 :(得分:2)

如果您想使用bdscale,请告诉它使用更多网格线:

ggplot(input) + 
  geom_segment(aes(x = xaxis, xend = xaxis, y = Low, yend = High), size = 0.50) +           # body 
  geom_segment(aes(x = xaxis - 0.4, xend = xaxis, y = Open, yend = Open), size = 0.90) +    # open
  geom_segment(aes(x = xaxis, xend = xaxis + 0.4, y = Close, yend = Close), size = 0.90)  + # close
  ggtitle("SPY: 2015") +
  xlab('') + ylab('') +
  scale_x_bd(business.dates=xaxis, max.major.breaks=10, labels=date_format("%b '%y")) # <==== !!!!

http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_SQLServer.html

它应该把十月放在那里的轴上,但它并不那么聪明。 Womp womp。拉请求欢迎!

答案 2 :(得分:1)

嗯,你可以手动调整它,但它有点hacky。首先,您应该使用索引,以便您的观察编号为1到188。

   input$xaxis <-index(as.Date(rownames(input)))

然后你自己的情节代码:

p <- ggplot(input)
p <- p + geom_segment(aes(x = xaxis, xend = xaxis, y = Low, yend = High), size = 0.50)           # body
p <- p + geom_segment(aes(x = xaxis - 0.4, xend = xaxis, y = Open, yend = Open), size = 0.90)    # open
p <- p + geom_segment(aes(x = xaxis, xend = xaxis + 0.4, y = Close, yend = Close), size = 0.90)  # close
p <- p + scale_y_continuous(scale_y_log10()) + ggtitle("SPY: 2015") 

最后,我查看了应该在哪里进行休息的输入,并手动提供了标签:

p + scale_x_continuous(breaks=input$xaxis[c(1,62,125,188)], labels=c("jan","apr","jul","oct"))

请注意,我是懒惰的,只花了1-jan,1-apr 1-jul和1-oct的最近日期,因为1 jan是假日,标签“jan”低于2-jan。我把标签“oct”放在30-sep以下,这是input中的最后一个条目。您可以根据需要对此进行调整。

当然,您可以自动化标签添加带有日期的标签字段并提取月份。

答案 3 :(得分:1)

下面的方法使用分面来删除缺失日期之间的空格,然后删除分面之间的空白区域以恢复未破坏的地块的外观。

首先,我们创建一个分组变量,每当日期中断时(代码改编自this SO answer),该变量会递增。我们稍后会将其用于分面。

input$group = c(0, cumsum(diff(input$xaxis) > 1))

现在我们将以下代码添加到您的图中。 facet_grid在每个位置创建一个新方面,因为周末或假日,日期顺序中断。 scale_x_date每周添加一次主要刻度线,每天添加次要网格线,但您可以调整此值。 theme函数删除了构面条标签和构面之间的垂直空间:

p + facet_grid(. ~ group, space="free_x", scales="free_x") +
  scale_x_date(breaks=seq(as.Date("2015-01-01"),max(input$xaxis), "1 week"), 
               minor_breaks="1 day",
               labels=date_format("%b %d, %Y")) +
  theme(axis.text.x=element_text(angle=-90, hjust=0.5, vjust=0.5, size=11),
        panel.margin = unit(-0.05, "lines"),
        strip.text=element_text(size=0),
        strip.background=element_rect(fill=NA)) +
  ggtitle("SPY: 2015")

这是结果图。周末和假期的空间消失了。每周都会有重大突破。我将scale_x_date breaks参数中的周数设置为星期四开始,因为星期四没有假期,因此每个方面都有一个主要的刻度标记。 (相比之下,默认休息时间会在星期一。由于假期通常在星期一,星期一假日的周数不会有默认休息时间的主要标记。)但是请注意,主要休息之间的间距本身就是根据当周市场开放的天数而有所不同。

enter image description here

答案 4 :(得分:1)

无法让OHLC工作 - 您认为自己需要自定义geom

我知道这不是你要求的,但我可以用美味的蜡烛图来诱惑你吗?

library(dplyr)
library(bdscale)
library(ggplot2)
library(quantmod)
library(magrittr)
library(scales)

getSymbols("SPY", from = Sys.Date() - 1460, to = Sys.Date(), adjust = TRUE, auto.assign = TRUE)

input <- data.frame(SPY["2015/"]) %>% 
  set_names(c("open", "high", "low", "close", "volume", "adjusted")) %>%
  mutate(date=as.Date(rownames(.)))

input %>% ggplot(aes(x=date, ymin=low, ymax=high, lower=pmin(open,close), upper=pmax(open,close), 
                     fill=open<close, group=date, middle=pmin(open,close))) + 
  geom_boxplot(stat='identity') +
  ggtitle("SPY: 2015") +
  xlab('') + ylab('') + theme(legend.position='none') +
  scale_x_bd(business.dates=input$date, max.major.breaks=10, labels=date_format("%b '%y"))

enter image description here