这是一种涉及的解决方案,但我相信它最好地回答了您的问题,即您希望在典型直方图旁边放置一个表示“>10”值(或非数字值)的条形图)。 至关重要的是,您要确保保持与直方图关联的“分箱”,这意味着您不希望简单地使您的比例尺成为离散比例尺并用典型的条形图表示直方图。
数据
由于您想保留直方图特征,我将使用一个示例数据集,该示例数据集比您提供给我们的要复杂一些。我只是要指定一个均匀分布(n=100),其中包含 20 个“>10”个值。
set.seed(123)
df<- data.frame(time=c(runif(100,0,10), rep(">10",20)))
正如准备的那样,df$time 是一个字符向量,但对于直方图,我们需要它是数字的。我们只是将其强制为数字并接受“>10”值将被强制为 NA。这很好,因为最后我们将计算那些 NA 值并用条形表示它们。在此过程中,我正在创建 df 的一个子集,该子集将用于使用 count() 函数创建代表我们的 NA (">10") 的条形,该函数返回一个由一行和列:df$n = 20 在这种情况下。
library(dplyr)
df$time <- as.numeric(df$time) #force numeric and get NA for everything else
df_na <- count(subset(df, is.na(time)))
情节
对于实际绘图,您要求创建 (1) 直方图和 (2) 条形图的组合。这些不是同一个图,但更重要的是,它们不能共享相同的轴,因为根据定义,直方图需要一个连续轴和“NA”值或“>10”不是数字/连续值。这里的解决方案是制作两个单独的图,然后通过cowplot 将它们与一点魔法结合起来。
直方图很容易创建。稍后我将保存垃圾箱的数量以用于演示目的。这是基本情节:
bin_num <- 12 # using this later
p1 <- ggplot(df, aes(x=time)) + theme_classic() +
geom_histogram(color='gray25', fill='blue', alpha=0.3, bins=bin_num)
由于之前的子集,NA 值的条形图也很容易:
p2 <- ggplot(df_na, aes(x=">10", y=n)) + theme_classic() +
geom_col(color='gray25', fill='red', alpha=0.3)
哎呀!这看起来很可怕,但要有耐心。
将它们拼接在一起
您可以简单地运行 plot_grid(p1, p2) 并得到一些可行的东西......但它还有很多不足之处:
这里有问题。我将列举它们,然后向您展示我如何处理它们的最终代码:
-
需要从 NA 条形图中删除一些元素。也就是说,完全是 y 轴和 x 轴的标题(但它不能是 NULL 或者 x 轴不会正确排列)。这些是theme() 元素,可以通过ggplot 轻松删除。
-
NA 条形图占用了太多空间。需要减少宽度。我们通过访问plot_grid() 的rel_widths= 参数来解决这个问题。轻松愉快。
-
我们如何知道如何设置 y 比例上限?这有点复杂,因为它将取决于p1 的..count.. stat 以及 NA 值的数量。您可以使用ggplot_build() 来access the maximum count for a histogram,它是ggplot2 的一部分。
因此,最终代码需要创建基本的 p1 和 p2 图,然后添加到它们以修复限制。我还在p1 中添加了 bin 数量的注释,以便我们可以跟踪上限设置的工作情况。这是代码和一些示例图,其中bin_num 分别设置为 12 和 5:
# basic plots
p1 <- ggplot(df, aes(x=time)) + theme_classic() +
geom_histogram(color='gray25', fill='blue', alpha=0.3, bins=bin_num)
p2 <- ggplot(df_na, aes(x=">10", y=n)) + theme_classic() +
geom_col(color='gray25', fill='red', alpha=0.3) +
labs(x="") + theme(axis.line.y=element_blank(), axis.text.y=element_blank(),
axis.title.y=element_blank(), axis.ticks.y=element_blank()
) +
scale_x_discrete(expand=expansion(add=1))
#set upper y scale limit
max_count <- max(c(max(ggplot_build(p1)$data[[1]]$count), df_na$n))
# fix limits for plots
p1 <- p1 + scale_y_continuous(limits=c(0,max_count), expand=expansion(mult=c(0,0.15))) +
annotate('text', x=0, y=max_count, label=paste('Bins:', bin_num)) # for demo purposes
p2 <- p2 + scale_y_continuous(limits=c(0,max_count), expand=expansion(mult=c(0,0.15)))
plot_grid(p1, p2, rel_widths=c(1,0.2))
所以,我们的上限修复工作。玩定位等和plot_grid() 函数可能会非常疯狂,但我认为这种方式效果很好。