【问题标题】:R barplots: specify intervals of date-based x-axisR条形图:指定基于日期的x轴的间隔
【发布时间】:2017-12-15 06:55:38
【问题描述】:

我一直在制作不同的图表集,全部以 R 为基础。我有条形图的问题。我已经格式化了 x 轴以按年份显示日期,但是,很多年会出现多次。我希望每年只出现一次。

这是我的示例代码:

library(quantmod)
start <- as.Date("01/01/2010", "%d/%m/%Y")

#Download FRED data
tickers <- c("WTISPLC", "DCOILBRENTEU")
fred <- lapply(tickers, function(sym) {na.omit(getSymbols(sym, src="FRED", auto.assign=FALSE, return.class = "zoo"))})
df <- do.call(merge, fred)

#Subset for start date
df <- subset(df, index(df)>=start)

#Create bar plot
par(mar = c(5,5,5,5))

barplot(df[,2], names.arg=format(index(df), "%Y"), ann=FALSE, bty="n", tck=-0, col=1:1,  border=NA, space=0); title(main="Example chart", ylab="y-axis")

这个例子应该是可重现的并且清楚地表明我的意思。现在,我一直在研究如何添加单独的 x 轴以及如何定义该轴。所以,我尝试添加以下代码:

#Plot bars but without x-axis
barplot(df[,2], names.arg=format(index(df), "%Y"), ann=FALSE, bty="n", tck=-0, xaxt="n", col=1:1,  border=NA, space=0); title(main="Example chart", ylab="y-axis")

# Set x-axis parameters
x_min <- min(index(df))
x_max <- max(index(df))
xf="%Y"

#Add x-axis
axis.Date(1, at=seq(as.Date(x_min), x_max, "years"), format=xf, las=1, tck=-0)

这不会给我一条错误消息,但它在绘制 x 轴方面也完全没有任何作用。

请不要为 ggplot 提供解决方案。尽管我喜欢 ggplot,但这些条形图对我来说是一个更大项目的一部分,全部使用 R 基础,我现在不想将 ggplot 引入这个项目。

谢谢!

【问题讨论】:

  • 我很难复制你的例子。如果您可以添加当前和预期结果的图像,这也会有所帮助。您是否考虑过在绘制数据之前汇总数据?例如df2=aggregate(df$DCOILBRENTEU[!is.na(df$DCOILBRENTEU)],by=format(index(df), "%Y")[!is.na(df$DCOILBRENTEU)],sum)
  • 如果我可以问,您在重现该示例时遇到的确切困难是什么?我添加了实际输出与所需输出的图像。谢谢,阿什利。
  • 我可以毫无问题地重现该示例。
  • 我在下面添加了一个纯barplot 解决方案。
  • 抱歉,我遇到了一些错误,但那是我这边的包的问题。无论如何,感谢您添加图片,这有帮助!

标签: r plot


【解决方案1】:

如果您不限于barplot,您可以使用以下非常简单的解决方案,在屏幕后面使用plot.zoo

# only use what you want, and avoid multiple plots
df2 <- df[ , 2]

# use zoo.plot's functionality
plot(df2, main = "Example Chart", ylab = "y-axis", xlab = "")

这会产生以下情节:

我知道这不是条形图,但我看不出条形图会在这里添加什么。请告诉我,这是否是您想要的。

编辑 1

如果您确实想使用barplot,您可以使用以下代码:

### get index of ts in year format
index_y <- format(index(df), "%Y")

### logical vector with true if it is the start of a new year
index_u <- !duplicated(index_y)

### index of start of new year for tick marks
at_tick <- which(index_u)

### label of start of new year
labels <- index_y[index_u]

### draw barplot without X-axis, and store in bp
### bp (bar midpoints) is used to set the ticks right with the axis function
bp <- barplot(df[,2], xaxt = "n", ylab= "y-axis") 
axis(side = 1, at = bp[at_tick] , labels = labels)

产生以下情节:

请告诉我,这是否是你想要的。

编辑 2

在解释为什么刻度和标签在左侧组合在一起时,我们需要考虑两个信息。

(1) 在barplotspace 中定义每个条形之前的空间量(作为平均条形宽度的一部分)。在我们的例子中,它默认为零左右(有关详细信息,请参阅?barplot)。在下图中,我们使用了 0.0、0.5 和 2.0 的空间

(2) Barplot 返回一个数字向量,其中绘制了条形的中点(有关更多详细信息,请再次参阅帮助页面)。我们可以使用这些中点向图中添加信息,就像我们在以下摘录中所做的那样:在将barplot 的结果存储在 bp 中之后,我们使用 bp 来设置滴答声:axis(... at = bp[at_tick] ... ).

当我们添加空间时,条形中点的位置会发生变化。因此,当我们想在添加空间后使用条形中点时,我们需要确保我们拥有正确的信息。简单地说,将 barplot 返回的向量与添加空间的调用一起使用。如果你不这样做,图表就会被弄乱。在下面,如果您继续使用 (space=0) 调用的条形中点,并增加空间,则刻度和标签将在左侧分组。

下面,我用您在 2017 年限制为 3 个月的数据来说明这一点。 在顶层绘制了 3 个条形图,space 等于 0.0、0.5 和 2.0。用于计算刻度和标签位置的信息会重新计算并保存在每个绘图中。

在底层,绘制了相同的 3 个条形图,但用于绘制刻度和标签的信息仅使用第一个图(空格=0.0)创建

# Subset for NEW start for illustration of space and bp
start2 <- as.Date("01/10/2017", "%d/%m/%Y")
df2 <- subset(df, index(df)>=start2)

### get index of ts in month format, define ticks and labels
index_y2 <- format(index(df2), "%m")
at_tick2 <- which(!duplicated(index_y2))
labels2 <- index_y2[!duplicated(index_y2)]

par(mfrow = c(2,3))
bp2 <- barplot(df2[,2], xaxt = "n", ylab= "y-axis", space= 0.0, main ="Space = 0.0") 
axis(side = 1, at = bp2[at_tick2] , labels = labels2)
bp2 <- barplot(df2[,2], xaxt = "n", ylab= "y-axis", space= 0.5, main ="Space = 0.5") 
axis(side = 1, at = bp2[at_tick2] , labels = labels2)
bp2 <- barplot(df2[,2], xaxt = "n", ylab= "y-axis", space= 2.0, main ="Space = 2.0") 
axis(side = 1, at = bp2[at_tick2] , labels = labels2) 
### the lower layer
bp2 <- barplot(df2[,2], xaxt = "n", ylab= "y-axis", space= 0.0, main ="Space = 0.0") 
axis(side = 1, at = bp2[at_tick2] , labels = labels2)
barplot(df2[,2], xaxt = "n", ylab= "y-axis", space= 0.5, main ="Space = 0.5") 
axis(side = 1, at = bp2[at_tick2] , labels = labels2)
barplot(df2[,2], xaxt = "n", ylab= "y-axis", space= 2.0, main ="Space = 2.0") 
axis(side = 1, at = bp2[at_tick2] , labels = labels2)
par(mfrow = c(1,1))

看看这里:

  • 顶层:bp 每次都重新计算
  • 底层:bp space=0重用

在控制台中剪切和粘贴命令可能比上图更能说明效果。

我希望这会有所帮助。

【讨论】:

  • 感谢您的解决方案。但是,我使用 barplot 的原因是最终添加一个辅助轴(在我上面的示例中未显示)并在右侧绘制变量的同比变化。在我看来,这种条形图和线图的组合看起来比两条线更好。
  • 您的解决方案似乎有效,但仅在 'space=0' 时有效。一旦我将空间增加到 > 0 的值,日期似乎会向左移动。你知道怎么解决吗?
  • @AshleyH。我在 Edit 2 下添加了图解说明。
【解决方案2】:

你可以使用axis函数,我用match来获取轴上日期的索引:

space=1
#Plot bars but without x-axis
barplot(df[,2], names.arg=format(index(df), "%Y"), ann=FALSE, bty="n", tck=-0, xaxt="n", 
       col=1:1,  border=NA, space=space); title(main="Example chart", ylab="y-axis")

# Set x-axis parameters
x_min <- min(index(df))
x_max <- max(index(df))

#Add x-axis
axis(1, at=match(seq(as.Date(x_min), x_max, "years"),index(df))*(1+space),
     labels = format(seq(as.Date(x_min), x_max, "years"),"%Y"),lwd=0)

希望这会有所帮助!

【讨论】:

  • 这正是我想要的,感谢 Florian!
  • 当我通过将参数 'space=1' 添加到 barplot 函数来更改 barplot 中条形的间距时,日期突然不再与日期对齐。你有解决方案吗?
  • 我猜 space=1 只是表示每个条之间有一个空条。尝试将 *2 添加到 at 参数,即 at=match(seq(as.Date(x_min), x_max, "years"),index(df))*2 我希望这可以解决您的问题。
  • @Florian,你说的不正确。查看barplot 的帮助页面,并查找空格。此外,简单的乘法并不是一个稳健的解决方案。我提供了一个解决方案,下面有解释。
  • 嗨 Koen,文档说明 the amount of space (as a fraction of the average bar width) left before each bar.,所以如果是一个,则有一个与一个条形完全相同宽度的空白空间。乘以 (1+space) 应该总是让标签位于正确的位置,还是我忽略了其他东西?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-29
  • 2020-11-20
  • 2018-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多