R 上带有 ggplot2 的样本大小的辅助 x 轴标签
Secondary x-axis labels for sample size with ggplot2 on R
我正在尝试使用 R 中的 ggplot2 复制我在 Excel 中制作的下图:
我能够使用 geom_line() 成功创建线条,使用 geom_text() / 一些手动调整和 y 轴创建标签。在下面找到我的代码:
library(readxl)
library(ggplot2)
somedata <- read_excel("somedata.xlsx")
somedata[,c(3:6)] <- somedata[,c(3:6)] * 100
somedata[,6] <- somedata[,6] + 25
somegraph <- ggplot(data = somedata, aes(x = date))
somegraph +
geom_point(aes(y = eligible_main), shape = 15, size = 4) +
geom_line(aes(y = eligible_main)) +
geom_line(aes(y = eligible_center), size = 2) +
geom_line(aes(y = eligible_upper), linetype = 2) +
geom_line(aes(y = eligible_lower), linetype = 2) +
scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, 10), labels = paste0(seq(0, 100, 10), "%")) +
labs(title = "Title", x = "Time", y = "Percentage") + theme_classic() +
theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(angle = 90, hjust = 1))
作为参考,这是我创建的一些假数据,其格式与我正在绘制的数据类似。您可以将其粘贴到 R 和 运行 我在控制台上面的代码中:http://s000.tinyupload.com/?file_id=43876540434394267818
但我发现在 x 轴上以相同方向创建样本大小的二级标签非常困难。在 ggplot2 或其他包中是否有一个简单的解决方案?另外,我可以在我的图表上添加注释线来指出完成后的事情吗?
非常感谢!
我有一个可能有用的解决方案。我无法获取您共享的数据,我创建了自己的虚拟数据集,如下所示:
set.seed(12345)
library(lubridate)
df <- data.frame(
dates=as.Date('2020-03-01')+days(0:9),
y_vals=rnorm(10, 50,7),
n=100
)
一、基本剧情:
library(scales)
library(ggrepel)
p.basic <- ggplot(df, aes(dates, y_vals)) +
geom_line() +
geom_point(size=2.5, shape=15) +
geom_text_repel(
aes(label=paste0(round(y_vals, 1), '%')),
size=3, direction='y', force=7) +
ylim(0,100) +
scale_x_date(breaks=date_breaks('day'), labels=date_format('%b %d')) +
theme_bw()
请注意,我的代码与您的略有不同。文本标签通过 ggrepel
包被推开。我还使用了 scales
中的一些函数来修复和设置日期轴的格式(另请注意 lubridate
是用于在上面的虚拟数据集中创建日期的包)。否则,相当标准的 ggplot
东西在那里。
对于轴外的文本,最好的方法是通过自定义注释,您必须在其中设置 grob。这里的做法如下:
移动轴 "down" 以便为额外文本留出空间。我们通过在轴标题顶部设置边距来做到这一点。
通过 coord_cartesian(clip='off')
关闭剪辑。这是需要的,以便通过允许在绘图区域外绘制内容来查看绘图外的注释。
遍历 df$n
的值,创建一个单独的 annotation_custom
object 通过 for
循环添加到图中。
代码如下:
p <- p.basic +
theme(axis.title.x = element_text(margin=margin(50,0,0,0))) +
coord_cartesian(clip='off')
for (i in 1:length(df$n)) {
p <- p + annotation_custom(
textGrob(
label=paste0('n=',df$n[i]), rot=90, gp=gpar(fontsize=9)),
xmin=df$dates[i], xmax=df$dates[i], ymin=-25, ymax=-15
)
}
p
高级选项带来更多乐趣
还有两件事要添加:注释(例如特定点的标注 + 文本),以及轴标签内容之间图下方的线条。
对于轴下方的线: 您可以通过 scale_...
和 breaks=
参数很容易地将 breaks=
添加到其他轴;然而,对于日期轴,它是……复杂的。这就是为什么我们将使用与上面相同的方法为轴下方的文本添加行。这里的想法是在下面的代码中将轴分成 sub.div
段,这取决于你的 x 轴上有多少个离散值。我可以这样做 in-line 几次...但是首先创建变量很有趣:
sub.div <- 1/length(df$n)
然后,我使用它通过再次使用 for
循环单独注释步骤 sub.div*i
中的线条来创建线条:
for (i in 1:(length(df$n)-1)) {
p <- p + annotation_custom(
linesGrob(
x=unit(c(sub.div*i,sub.div*i), 'npc'),
y=unit(c(0,-0.2), 'npc') # length of the line below axis
)
)
}
我知道我这里没有两端的线条,但你可能会看到通过修改上面的方法添加它是多么容易。
注释(有箭头,为什么不呢?): 有很多方法可以做注释。 Some are covered here using the annotate()
function. As well as here。如果您愿意,可以使用 annotate()
,但在本例中,我将使用 geom_label
作为文本标签,使用 geom_curve
来制作一些弯曲的箭头。
您可以通过调用每个注释的两个函数手动传递单个 aes()
值。例如,geom_text(aes(x=as.Date('2020-03-01'), y=55,...
,但如果您的数据集中有一些,建议根据数据框本身的信息设置注释。我先在这里做,我们将在其中标记两点:
df$notes <- c('','','','Wow!','','','OMG!!!','','','')
您可以使用 df$notes
的值来指示哪些点被标记,还可以利用同一数据集中 x
和 y
值的映射.
然后你只需要将这两个 geom 添加到你的 plot 中,根据你的喜好进行修改。
p <- p + geom_curve(
data=df[which(df$notes!=''),],
mapping=aes(x=dates+0.5, xend=dates, y=y_vals+20, yend=y_vals+2),
color='red', curvature = 0.5,
arrow=arrow(length=unit(5,'pt'))
) +
geom_label(
data=df[which(df$notes!=''),],
aes(y=y_vals+20, label=notes),
size=4, color='red', hjust=0
)
最后一件事:水平线 我之前在你的代码中注意到的最后一件事,但忘了指出,要制作你的水平线,只需使用 geom_hline
.这要容易得多。此外,您可以通过两次调用 geom_hline
非常轻松地完成此操作(如果您希望将数据帧传递给函数,甚至只需一次调用即可):
p <- p + geom_hline(yintercept = 50, size=2, color='gray30') +
geom_hline(yintercept = c(25,75), linetype=2, color='gray30')
请注意,建议在 geom_line
或 [=45] 之前添加这两个 geom_hline
调用 =] 在原来的 p.basic
情节中,所以他们落后于其他一切。
我正在尝试使用 R 中的 ggplot2 复制我在 Excel 中制作的下图:
我能够使用 geom_line() 成功创建线条,使用 geom_text() / 一些手动调整和 y 轴创建标签。在下面找到我的代码:
library(readxl)
library(ggplot2)
somedata <- read_excel("somedata.xlsx")
somedata[,c(3:6)] <- somedata[,c(3:6)] * 100
somedata[,6] <- somedata[,6] + 25
somegraph <- ggplot(data = somedata, aes(x = date))
somegraph +
geom_point(aes(y = eligible_main), shape = 15, size = 4) +
geom_line(aes(y = eligible_main)) +
geom_line(aes(y = eligible_center), size = 2) +
geom_line(aes(y = eligible_upper), linetype = 2) +
geom_line(aes(y = eligible_lower), linetype = 2) +
scale_y_continuous(limits = c(0, 100), breaks = seq(0, 100, 10), labels = paste0(seq(0, 100, 10), "%")) +
labs(title = "Title", x = "Time", y = "Percentage") + theme_classic() +
theme(plot.title = element_text(hjust = 0.5), axis.text.x = element_text(angle = 90, hjust = 1))
作为参考,这是我创建的一些假数据,其格式与我正在绘制的数据类似。您可以将其粘贴到 R 和 运行 我在控制台上面的代码中:http://s000.tinyupload.com/?file_id=43876540434394267818
但我发现在 x 轴上以相同方向创建样本大小的二级标签非常困难。在 ggplot2 或其他包中是否有一个简单的解决方案?另外,我可以在我的图表上添加注释线来指出完成后的事情吗?
非常感谢!
我有一个可能有用的解决方案。我无法获取您共享的数据,我创建了自己的虚拟数据集,如下所示:
set.seed(12345)
library(lubridate)
df <- data.frame(
dates=as.Date('2020-03-01')+days(0:9),
y_vals=rnorm(10, 50,7),
n=100
)
一、基本剧情:
library(scales)
library(ggrepel)
p.basic <- ggplot(df, aes(dates, y_vals)) +
geom_line() +
geom_point(size=2.5, shape=15) +
geom_text_repel(
aes(label=paste0(round(y_vals, 1), '%')),
size=3, direction='y', force=7) +
ylim(0,100) +
scale_x_date(breaks=date_breaks('day'), labels=date_format('%b %d')) +
theme_bw()
请注意,我的代码与您的略有不同。文本标签通过 ggrepel
包被推开。我还使用了 scales
中的一些函数来修复和设置日期轴的格式(另请注意 lubridate
是用于在上面的虚拟数据集中创建日期的包)。否则,相当标准的 ggplot
东西在那里。
对于轴外的文本,最好的方法是通过自定义注释,您必须在其中设置 grob。这里的做法如下:
移动轴 "down" 以便为额外文本留出空间。我们通过在轴标题顶部设置边距来做到这一点。
通过
coord_cartesian(clip='off')
关闭剪辑。这是需要的,以便通过允许在绘图区域外绘制内容来查看绘图外的注释。遍历
df$n
的值,创建一个单独的annotation_custom
object 通过for
循环添加到图中。
代码如下:
p <- p.basic +
theme(axis.title.x = element_text(margin=margin(50,0,0,0))) +
coord_cartesian(clip='off')
for (i in 1:length(df$n)) {
p <- p + annotation_custom(
textGrob(
label=paste0('n=',df$n[i]), rot=90, gp=gpar(fontsize=9)),
xmin=df$dates[i], xmax=df$dates[i], ymin=-25, ymax=-15
)
}
p
高级选项带来更多乐趣
还有两件事要添加:注释(例如特定点的标注 + 文本),以及轴标签内容之间图下方的线条。
对于轴下方的线: 您可以通过 scale_...
和 breaks=
参数很容易地将 breaks=
添加到其他轴;然而,对于日期轴,它是……复杂的。这就是为什么我们将使用与上面相同的方法为轴下方的文本添加行。这里的想法是在下面的代码中将轴分成 sub.div
段,这取决于你的 x 轴上有多少个离散值。我可以这样做 in-line 几次...但是首先创建变量很有趣:
sub.div <- 1/length(df$n)
然后,我使用它通过再次使用 for
循环单独注释步骤 sub.div*i
中的线条来创建线条:
for (i in 1:(length(df$n)-1)) {
p <- p + annotation_custom(
linesGrob(
x=unit(c(sub.div*i,sub.div*i), 'npc'),
y=unit(c(0,-0.2), 'npc') # length of the line below axis
)
)
}
我知道我这里没有两端的线条,但你可能会看到通过修改上面的方法添加它是多么容易。
注释(有箭头,为什么不呢?): 有很多方法可以做注释。 Some are covered here using the annotate()
function. As well as here。如果您愿意,可以使用 annotate()
,但在本例中,我将使用 geom_label
作为文本标签,使用 geom_curve
来制作一些弯曲的箭头。
您可以通过调用每个注释的两个函数手动传递单个 aes()
值。例如,geom_text(aes(x=as.Date('2020-03-01'), y=55,...
,但如果您的数据集中有一些,建议根据数据框本身的信息设置注释。我先在这里做,我们将在其中标记两点:
df$notes <- c('','','','Wow!','','','OMG!!!','','','')
您可以使用 df$notes
的值来指示哪些点被标记,还可以利用同一数据集中 x
和 y
值的映射.
然后你只需要将这两个 geom 添加到你的 plot 中,根据你的喜好进行修改。
p <- p + geom_curve(
data=df[which(df$notes!=''),],
mapping=aes(x=dates+0.5, xend=dates, y=y_vals+20, yend=y_vals+2),
color='red', curvature = 0.5,
arrow=arrow(length=unit(5,'pt'))
) +
geom_label(
data=df[which(df$notes!=''),],
aes(y=y_vals+20, label=notes),
size=4, color='red', hjust=0
)
最后一件事:水平线 我之前在你的代码中注意到的最后一件事,但忘了指出,要制作你的水平线,只需使用 geom_hline
.这要容易得多。此外,您可以通过两次调用 geom_hline
非常轻松地完成此操作(如果您希望将数据帧传递给函数,甚至只需一次调用即可):
p <- p + geom_hline(yintercept = 50, size=2, color='gray30') +
geom_hline(yintercept = c(25,75), linetype=2, color='gray30')
请注意,建议在 geom_line
或 [=45] 之前添加这两个 geom_hline
调用 =] 在原来的 p.basic
情节中,所以他们落后于其他一切。