【问题标题】:ggplot2: yearmon scale and geom_barggplot2:yearmon 比例和 geom_bar
【发布时间】:2017-10-17 21:29:02
【问题描述】:

我想了解的不仅仅是一个解决方案,为什么有些事情应该很容易,但实际上并非如此。

[我从另一篇涉及该问题的帖子中借用了部分代码,但最终得到了一个我不喜欢的解决方案]

library(ggplot2)
library(xts)
library(dplyr)
library(scales)

csvData <- "dt,status
2015-12-03,1
2015-12-05,1
2015-12-05,0
2015-11-24,1
2015-10-17,0
2015-12-18,0
2016-06-30,0
2016-05-21,1
2016-03-31,0
2015-12-31,0"

tmp <- read.csv(textConnection(csvData))
tmp$dt <- as.Date(tmp$dt)
tmp$yearmon <- as.yearmon(tmp$dt)
tmp$status <- as.factor(tmp$status)

### Not good. Why?
ggplot(tmp, aes(x = yearmon, fill = status)) + 
  geom_bar() + 
  scale_x_yearmon()

### Almost good but long-winded and ticks not great
chartData <- tmp %>%
  group_by(yearmon, status) %>%
  summarise(count = n()) %>%
  as.data.frame()
ggplot(chartData, aes(x = yearmon, y = count, fill = status)) + 
  geom_col() + 
  scale_x_yearmon()

第一个情节全错了;第二个几乎是完美的(X 轴上的刻度不是很好,但我可以忍受)。 geom_bar() 不是应该执行我必须在第二个图表中手动执行的计数工作吗?

第一张图表

第二张图表

我的问题是:为什么第一张图表这么差?有一个警告是为了暗示一些东西(“position_stack 需要不重叠的 x 间隔”),但我真的无法理解它。 谢谢。

我的个人回答

这是我学到的(非常感谢你们所有人!):

  • 即使有scale_#_yearmonscale_#_date,不幸的是ggplot 将这些对象类型视为连续数字。这使得geom_bar 无法使用。
  • geom_histogram 可能会成功。但是您无法控制美学的相关部分。
  • 底线:您需要在绘制图表之前进行分组/求和
  • 不确定(如果您打算使用 ggplot2)xtslubridate 对于我想要实现的目标是否真的有用。我怀疑对于任何连续的案例 - 从日期来看 - 它们都是完美的。

总而言之,我以这个完美地完成了我所追求的结束(注意如何不需要 xtslubridate):

library(ggplot2)
library(dplyr)
library(scales)

csvData <- "dt,status
2015-12-03,1
2015-12-05,1
2015-12-05,0
2015-11-24,1
2015-10-17,0
2015-12-18,0
2016-06-30,0
2016-05-21,1
2016-03-31,0
2015-12-31,0"

tmp <- read.csv(textConnection(csvData))
tmp$dt <- as.Date(tmp$dt)
tmp$yearmon <- as.Date(format(tmp$dt, "%Y-%m-01"))
tmp$status <- as.factor(tmp$status)

### GOOD
chartData <- tmp %>%
  group_by(yearmon, status) %>%
  summarise(count = n()) %>%
  as.data.frame()

ggplot(chartData, aes(x = yearmon, y = count, fill = status)) + 
  geom_col() + 
  scale_x_date(labels = date_format("%h-%y"),
               breaks = seq(from = min(chartData$yearmon), 
                            to = max(chartData$yearmon), by = "month"))

最终输出

【问题讨论】:

  • 我没有看到第一个和第二个情节之间有任何区别。你能发布你的情节图片并指出第一个情节有什么问题吗?
  • 按要求完成。这可能是平台/软件包版本的某种问题吗?我在WIN10; R版本3.4.0(2017-04-21); ggplot2 2.2.1
  • 我会改用:ggplot(tmp, aes(x = floor_date(dt, "month"), fill = status)) + geom_bar() + scale_x_date(labels = date_format("%Y- %b")),从而提供更好的 x 轴。
  • floor_date() 来自 lubridate 包,是吗?无论如何:我得到的结果与上面的第一张图表完全相同。
  • 使用 ggplot2 3.3.0 它不起作用

标签: r ggplot2 xts


【解决方案1】:

第一个情节被搞砸的原因基本上是ggplot2并不完全是yearmon。正如你在这里看到的,它只是一个内部带有标签的num

> as.numeric(tmp$yearmon)
[1] 2015.917 2015.917 2015.917 2015.833 2015.750 2015.917 2016.417 2016.333 2016.167 2015.917

因此,当您在没有先前聚合的情况下进行绘图时,条形图会展开。您需要像这样使用geom_histogram() 分配适当的binwidth

ggplot(tmp, aes(x = yearmon, fill = status)) + 
  geom_histogram(binwidth = 1/12) + 
  scale_x_yearmon()

1/12对应每年12个月。

对于聚合后的绘图,正如@ed_sans 建议的那样,我也更喜欢lubridate,因为我更了解如何更改刻度和修改轴标签。

chartData <- tmp %>%
  mutate(ym = floor_date(dt,"month")) %>%
  group_by(ym, status) %>%
  summarise(count = n()) %>%
  as.data.frame()

ggplot(chartData, aes(x = ym, y = count, fill = status)) + 
  geom_col() + 
  scale_x_date(labels = date_format("%Y-%m"),
               breaks = as.Date("2015-09-01") + 
                 months(seq(0, 10, by = 2)))

【讨论】:

    【解决方案2】:

    您也可以aes(x=factor(yearmon), ...) 作为快捷方式修复。

    【讨论】:

      猜你喜欢
      • 2017-11-29
      • 2018-03-17
      • 1970-01-01
      • 1970-01-01
      • 2015-10-19
      • 1970-01-01
      • 2019-05-03
      • 2018-04-09
      • 1970-01-01
      相关资源
      最近更新 更多