如何移除ggplot2背景并裁剪geom_col周围的边距

4
我希望使用堆叠柱状图制作一个“时间轴”。我想做的是去除所有背景,只留下一根条形图。但是我卡在了图表的白色背景上。
这是一个最简示例:
mytheme <-  theme(
        axis.title.x=element_blank(),
        axis.text.x=element_blank(),
        axis.ticks.x=element_blank(),
        axis.title.y=element_blank(),
        axis.text.y=element_blank(),
        axis.ticks.y=element_blank(),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        #panel.background = element_blank()
)

Name <- c("One", "Two", "Three", "Four")
value <- c(2, 5, 7, 8)

df <-  data.frame(Name, value)

ggplot(df)+
  aes(x= "Name", y = value,  fill = Name) +
  geom_col(width = .1, show.legend = FALSE) + 
  xlab("") + ylab("") +
  coord_flip() +
  mytheme

给我一个条形图,但是背景很大。 shown here。(为了显示背景的范围,我已经注释掉了panel.background。我想“裁剪”那个白色背景,只留下条形图或者只有一点空间围绕着条形图。请帮忙。更新:在@Gregor的建议下,我修改了代码ggplot如下:)
ggplot(df)+
  aes(x= "Name", y = value,  fill = Name) +
  geom_col(width = .1, show.legend = FALSE) + 
  xlab("") + ylab("") +
  coord_flip(expand = FALSE) +
  mytheme

结果是一根非常宽的条形图(因为我使用了coord_flip,所以在页面上很高): enter image description here 现在我需要做的就是缩小高度(如图片所示),使其更像原来的条形图。我该怎么改变呢?
解决方案:
我最终找到了一个简单的解决方案。由于我正在使用R Markdown,我使用了:
```{r, ..., fig.width=4, fig.height=.3}

在嵌入图形的前置条件中。虽然不是最好的解决方案,但它确实有效。感谢大家。


5
几个想法(但不是完整的答案):(a)将 x = "Name" 改为 aes(x = 1),数值型的 x 轴会填充空间并随着调整自动调整大小。(b)在 coord 调用内使用 expand = FALSE。(c)使用 coord_fixed 替代 coord_flip - 这意味着您需要使用 geom_tile 而不是 geom_col 来获得横向的结果。 - Gregor Thomas
谢谢@Gregor。很有用的提示。expand = FALSE很有意思。我正在努力理解ggplot2的基础知识,所以还不是很熟练。也在看geom_tile - Kaveh1000
我也有一些想法,但真的没有好的答案。如果您使用其他设备,如png、pdf或其他任何设备,可以在主题中尝试使用plot.margin=unit(c(-100,-2,-100,-2), "cm"),然后在输出设备中缩小它,例如ggsave("plot.png", width = 5, height = 1) - Darek Bienkowski
我已经使用了 coord_flip(expand = FALSE)aes(x = 1)。现在我有了一个没有边框的“粗”条形图。因此,在上面的图表中,高度已经增加了。我只需要知道如何减小那个高度。谢谢。 - Kaveh1000
@Kaveh1000 你能否调整你的图形设备大小?(例如,如果你要将结果保存到图像文件中,在png()jpeg()等函数中更改高度/宽度) - Z.Lin
显示剩余2条评论
1个回答

4
这是一个非常有趣的问题。以下是一种方法来解决:我们可以创建一个“正常”的条形图,其中每个条形相邻并且高度相等,但每个条形的宽度都是您所需时间间隔的持续时间。使用coord_fixed(expand = FALSE)可以裁剪背景。
最好直接向 ggplot() 指定 x 轴位置,以便我们可以使用它们来放置标签(稍后会详细说明)。下面是如何为您的时间轴定位间隔:
Xi 表示每个时间间隔 i 的中心点到原点的距离(沿着 x 轴)。对于每个间隔 iXi 是前面时间间隔 X0 : Xi - 1 的长度之和加上 Xi 长度的一半。我们可以添加一列使用滞后累计总和来让 R 自动为我们生成这些值,如下所示。
我已经将panel.background = element_blank()注释掉,以便您可以确认我们确实只获得了“时间轴”,没有其他背景。

代码:

library("tidyverse")

mytheme <-  theme(
  axis.title.x=element_blank(),
  axis.text.x=element_blank(),
  axis.ticks.x=element_blank(),
  axis.title.y=element_blank(),
  axis.text.y=element_blank(),
  axis.ticks.y=element_blank(),
  panel.grid.major = element_blank(),
  panel.grid.minor = element_blank(),
  #panel.background = element_blank()
)

Name <- c("One", "Two", "Three", "Four")
Value <- c(2, 5, 7, 8)

df <-  data.frame(Name, Value) %>%
  mutate(Name = factor(Name, levels = Name),
         xPos = cumsum(lag(Value, default = 0)) + Value/2) # calculate interval position

ggplot(data = df, aes(x = xPos, y = 1, width = Value, fill = Name)) +
  geom_col(position = "identity",
           show.legend = FALSE) +
  geom_text(aes(label = Name),
            position = position_fill(vjust = 0.5)) +
  coord_fixed(expand = FALSE) + # crop background around geom_col()
  mytheme

输出:

Timeline Plot

为什么有效:

ggplot2 3.1.0版本开始,我们面临两难抉择:如果我们选择使用coord_flip(),我们可以得到一个水平时间轴,但我们无法(容易地)调整绘图区域的尺寸以符合我们的要求。如果我们改用coord_fixed(expand = FALSE),我们就有了所需的绘图边距,但我们无法很容易地创建水平的“堆积”条形图,因为coord_fixed()coord_flip()不兼容。

有一个有趣的参数叫作position_dodge2(),你可以使用它和geom_col()将宽度可变的条形图相邻放置。如果设置padding=0,你就可以获得一个非常类似于上面看到的图表,但每个间隔的实际“x坐标”将从每个条形的左边缘开始,而不是中心。

这使得居中文本标签非常困难,因为我们需要根据每个间隔的宽度来调整它们的位置,但ggplot2选项如position_nudge()只允许我们调整所有标签的位置。因此,我们直接指定每个时间间隔的中心。希望随着ggplot2的不断改进,我们会看到像position_nudge()这样的选项获得更多的功能,以更轻松地解决这个问题!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接