ggplot2-如何使用geom_bar绘制时间长度?

问题描述

我试图通过在多个区域显示作物种植和收获日期来显示不同的生长季节长度。

我的最终目标是一个如下所示的图形:

enter image description here

是从对this question的答复中摘录的。请注意,日期以儒略日(一年中的天)为单位。

我重现类似情节的第一次尝试是:

@H_404_10@library(data.table) library(ggplot2) mydat <- "Region\tCrop\tPlanting.Begin\tPlanting.End\tHarvest.Begin\tHarvest.End\nCenter-West\tSoybean\t245\t275\t1\t92\nCenter-West\tCorn\t245\t336\t32\t153\nSouth\tSoybean\t245\t1\t1\t122\nSouth\tCorn\t183\t336\t1\t153\nSoutheast\tSoybean\t275\t336\t1\t122\nSoutheast\tCorn\t214\t336\t32\t122" # read data as data table mydat <- setDT(read.table(textConnection(mydat),sep = "\t",header=T)) # melt data table m <- melt(mydat,id.vars=c("Region","Crop"),variable.name="Period",value.name="value") # plot stacked bars ggplot(m,aes(x=Crop,y=value,fill=Period,colour=Period)) + geom_bar(stat="identity") + facet_wrap(~Region,nrow=3) + coord_flip() + theme_bw(base_size=18) + scale_colour_manual(values = c("Planting.Begin" = "black","Planting.End" = "black","Harvest.Begin" = "black","Harvest.End" = "black"),guide = "none")

enter image description here

但是,此情节存在一些问题:

  1. 由于条形图被堆叠,因此x轴上的值被聚合并且最终太高-超出了表示一年中某一天的1-365比例。

  2. 我需要以相同的颜色组合Planting.BeginPlanting.End,并对Harvest.BeginHarvest.End进行相同的操作。

  3. 此外,还需要在Planting.BeginHarvest.End之间创建一个“ void”(或完全无色的条形)。

也许图{em> 可以用geom_rectgeom_segment来实现,但是我真的想坚持使用geom_bar,因为它更具可定制性(例如,它接受scale_colour_manual以便为条形添加黑色边框。

关于如何创建这种图形的任何提示吗?

解决方法

我不认为您可以使用geom_bargeom_col做这件事。一种更通用的方法是使用geom_rect绘制矩形。为此,我们需要对数据进行一些重塑

plotdata <- mydat %>% 
  dplyr::mutate(Crop = factor(Crop)) %>% 
  tidyr::pivot_longer(Planting.Begin:Harvest.End,names_to="period") %>% 
  tidyr::separate(period,c("Type","Event")) %>% 
  tidyr::pivot_wider(names_from=Event,values_from=value)


#    Region      Crop    Type     Begin   End
#    <chr>       <fct>   <chr>    <int> <int>
#  1 Center-West Soybean Planting   245   275
#  2 Center-West Soybean Harvest      1    92
#  3 Center-West Corn    Planting   245   336
#  4 Center-West Corn    Harvest     32   153
#  5 South       Soybean Planting   245     1
#  ...

我们已经使用tidyr来对数据进行整形,因此每个矩形要绘制一行,并且将“裁剪”作为因素。然后我们可以像这样绘制它

ggplot(plotdata) + 
  aes(ymin=as.numeric(Crop)-.45,ymax=as.numeric(Crop)+.45,xmin=Begin,xmax=End,fill=Type) + 
  geom_rect(color="black") + 
  facet_wrap(~Region,nrow=3) + 
  theme_bw(base_size=18) +
  scale_y_continuous(breaks=seq_along(levels(plotdata$Crop)),labels=levels(plotdata$Crop))

enter image description here

这里有些混乱的地方是我们为y使用离散标度,但是geom_rect更喜欢数值,因此由于这些值现在是因子,因此我们将数值用于因子以创建ymin和ymax位置。然后,我们将y轴替换为因子级别的名称。

如果您还想获取x轴上的月份名称,可以执行类似的操作

dateticks <- seq.Date(as.Date("2020-01-01"),as.Date("2020-12-01"),by="month")
# then add this to you plot
  ... + 
    scale_x_continuous(breaks=lubridate::yday(dateticks),labels=lubridate::month(dateticks,label=TRUE,abbr=TRUE))