ggplot:防止年末数据显示为下一年

时间:2017-12-24 01:15:59

标签: r plot ggplot2 lubridate

这似乎是一个简单的问题,但我找不到一个简单的方法来做到这一点,类似的问题似乎没有解决我的问题。

我正在绘制年终数据,并希望它在x轴上显示为当年,而不是第二年。例如,2015年12月31日的数据反映了2015年发生的情况,而不是2016年,但情节将显示为2016年。

我可以改变数据并在变异列中添加仅年份值(2015年12月31日变为2015)并使用它来绘制数据集,但我希望有更简单的事情,以防我想要绘制其他时间段(季度,月份等)。

所以2个问题:

1)是否有一种简单的方法可以自动绘制年终数据,以表示其发生的年份,而不是下一年?

2)当我试图调整x轴刻度时,为什么ggplot会删除2行,导致绘图更糟(test_p2)?

可重复的示例

library(ggplot2)
library(lubridate)

# Sample data
mydates   <- as.Date(c( "2015-12-31", "2016-12-31", "2017-12-23", "2015-12-31", "2016-12-31", "2017-12-23"))
variables <- c(rep("A", 3), rep("B", 3))
values    <- c(2, 4, -4, -5, -10, 5)
test_df   <- data.frame(mydates, variables, values)

# plot
test_p <- ggplot(test_df, aes(x = mydates, y = values, fill = variables)) + geom_col(position = "dodge")
test_p

enter image description here

调整x轴刻度:

BeginPlotDate   = "2015-12-31"
EndPlotDate     = "2017-12-23"

test_p2 <- test_p + scale_x_date(date_breaks = "1 year",
                                 date_labels = "%Y",
                                 limits      = as.Date(c(BeginPlotDate, EndPlotDate))
                                 )
test_p2

enter image description here

2 个答案:

答案 0 :(得分:1)

你通常不应该一次问两个问题,但无论如何,这里有两个答案:

问题1

ggplot2会将日期四舍五入到最接近的一年,而第二年就是这样。我认为解决这个问题的最简单方法是在aes()声明中简单地减去12个月:

test_p <- ggplot(test_df,
                 aes(x = mydates %m-% months(12),
                     y = values, fill = variables)) + 
          geom_col(position = "dodge")
test_p

enter image description here

唯一的缺点是现在你需要手动调整x轴的标题,但这很简单,例如与xlab()

test_p + xlab("my dates")

enter image description here

问题2

您将x轴的起点设置为&#34; 2015-12-31&#34;,这正是ggplot的作用。您需要将起点设置为较早的日期(大约提前6个月),以便为要在其中绘制的条形图留出足够的空间。 (在这里,我实际上必须在18个月之前设置它,因为我也从日期中减去了12个月,见上文。)

BeginPlotDate   = "2014-06-01"
EndPlotDate     = "2017-08-01"

test_p2 <- test_p + scale_x_date(date_breaks = "1 year",
                                 date_labels = "%Y",
                                 limits      = as.Date(c(BeginPlotDate, EndPlotDate))
)
test_p2

enter image description here

答案 1 :(得分:1)

问题有一个相当简单的解决方案:只需使用year(mydates)

library(ggplot2)
library(lubridate)

ggplot(test_df, aes(x = year(mydates), y = values, fill = variables)) + 
  geom_col(position = "dodge")

enter image description here

在绘制DatePOSIXct时,ggplot2采用连续比例,通过在适当的位置放置标记清晰的刻度标记来形成,例如,2016年会有刻度线-01-01,标有&#34; 2016&#34;。因此,如果您的数据点的x值为2015-12-31,则会在2016-01-01刻度线附近绘制。这对于每日或每周数据很有用,但在您的用例中则不行。

修改

OP已经指出他需要一个日期轴,因为他也希望绘制月度和季度数据。

如果OP希望使用连续日期轴在一个图中叠加月度,季度和年度数据,那么我强烈建议不要使用条形图目的,特别是当被躲避时。

条形图通常用于离散数据。条的高度传达信息。通常,宽度没有意义,可以任意选择或美学上令人愉悦。

如果OP坚持在日期轴上,则宽度具有含义。例如,水平扩展可以传达每个值被分配给哪个时间段的信息,例如,

ggplot(test_df, aes(x = floor_date(mydates, "year"), xend = mydates, 
                    y = values, yend = values, colour = variables)) + 
  geom_segment(size = 1) +
  theme_bw()

enter image description here

此处,线段从年初开始并延伸到给定的结束日期。这可视化values代表年度值。躲避对她没有任何意义,因此颜色代码是variables之间唯一的区别。

一个更复杂的例子(使用特别制作的数据)在一个图表中显示月度值,季度和年度平均值:

ggplot(month_df) + 
  aes(x = mydates, xend = floor_date(mydates, first(period)), 
      xmin = floor_date(mydates, first(period)), xmax = mydates,
      y = values, yend = values, ymin = 0, ymax = values, 
      fill = variables, shape = variables) + 
  geom_rect(data = year_df, alpha = 0.5)  +
  geom_segment(aes(colour = variables), data = quarter_df, size = 1) + 
  geom_point() +
  theme_bw()

enter image description here

然而,图表相当复杂,图表的信息难以解释和察觉。

数据

library(data.table)
# create monthly dummy data
month_df <- data.table(
  # last day of month
  mydates = rep(seq(as.Date("2015-02-01"), length.out = 36L, by = "month") - days(1L), 2L),
  variables = rep(LETTERS[1:2], each = 36L),
  values = c(sinpi((1:36) / 18), cospi((1:36) / 12)),
  period = "month"
)
# aggregate by quarter
quarter_df <- month_df[, .(values = mean(values), period = "quarter"), 
     by = .(mydates = ceiling_date(mydates, "quarter") - days(1L), variables)]
# aggregate by year
year_df <- month_df[, .(values = mean(values), period = "year"), 
     by = .(mydates = ceiling_date(mydates, "year") - days(1L), variables)]