部分虚线 ggplot

5
我是R的新手,已经使用ggplot制作了一张多线图。在x轴上,我有5个离散时间点。我想让折线图的后半部分变成虚线(见附图),请问有人可以帮助我编辑当前代码以实现这个目标吗?非常感谢您提前的帮助!
ggplot(longdata, aes(x = Time, y = Strength, colour = Group)) +
  stat_summary(fun  = mean,
               geom = "point",)+ 
  stat_summary(fun = mean,
               geom = "line", 
               aes(group = Group), size =1,
               show.legend = FALSE) + 
               geom = "errorbar",
               width = .1, alpha = 0.3) +
  xlab("Testing Timepoint") +
  ylab("Isometric Strength (N.m)") +
  bbtheme +
  scale_colour_manual(name = "Group",
                      labels = c("Once-weekly", "Twice-weekly"),
                      values = c("red1", "navyblue")) +
  expand_limits(y = 0)
2个回答

10

这里提供了一个建议方法。建议您发布您的数据集或示例数据集,以便在未来的问题中更容易地为您的问题提供解决方案。将 dput(your.data.frame) 的输出粘贴在此处是共享数据框架的最佳方式之一。

话虽如此,这里有一个示例数据集。我们将用它绘制线图。

df <- data.frame(x=1:10, y=1:10)
p <- ggplot(df, aes(x,y)) + theme_bw()
p + geom_line()

在此输入图片描述

非常惊人。假设你想将该行分成x=5后为虚线,x=5前为实线,你可以采取以下方法之一:

  1. 在数据集中创建另一列,并将 linetype 的美学映射到该列(这是首选选项),或者

  2. 内联设置语句以映射 linetype 的美学。较不优先,但也可以。

我们将使用上述的第二种方法,因为它足够简单。像这样的东西可能有效:

p + geom_line(aes(linetype=eval(x>5)))

这里输入图片描述

糟糕。它“起作用”了,但是出现了间隙。ggplot正在绘制线条介于点之间,因此如果一个点包含在一个集合中,则不包含在另一个集合中。我在x=1和x=4之间画了一条实线,然后在x=5和x=10之间画了一条虚线。我们希望它在x=1和x=5之间画一条实线,然后在x=5和x=10之间画一条虚线。你现在看到问题了吗?我们需要x = 5同时属于两个集合。

这里的解决方案是我们需要调用两次geom_line。可能还有另一种方法,但这是我会做的方法:

p + geom_line(data=subset(df, x<=5), linetype=1) +
    geom_line(data=subset(df, x>=5), linetype=2)

在此输入图像描述

成功了。现在,如果您想添加一些标签的图例,您需要在ggplot中指定“我要为线条类型添加一个图例”。通过在每个geom_line调用中包含linetype=aes()内来实现。然后,您可以通过scale_linetype_manual手动指定该图例的各个方面。就像这样:

p + geom_line(data=subset(df, x<=5), aes(linetype='solid line')) +
    geom_line(data=subset(df, x>=5), aes(linetype='dotted line')) +
    scale_linetype_manual('type of line', values=c(2,1))

在此输入图像描述

编辑:如何处理非数字x轴?

根据您的说明,我将整合u/jpsmith 在这里的回复中提到的内容,即如何处理非数字x轴。正如@jpsmith所指出的,你需要使用stat_summary,因为如果你尝试使用geom_line它会抱怨。首先确保x轴值为因子,然后提取levels(longdata$Time)。你可能需要先确保levels(longdata$Time)按正确的顺序排列,但从你展示的图中看来,似乎是这样。然后,准备每种线的包含点可能是值得的,一定要在两个集合中都包含“Post”:

solid.line.points <- c('Pre', 'Mid', 'Post')
dashed.line.points <- c('Post', 'Mid.detraining', 'Post.detraining')

然后,使用stat_summary,就像@jpsmith发布的那样。请注意一些关键更改,如应用于您的情况:

stat_summary(data=subset(df,Time %in% solid.line.points),
    fun=mean, geom="line",
    inherit.aes=FALSE, aes(x=Time, y=Strength, linetype='solid line')) +
stat_summary(data=subset(df,Time %in% dashed.line.points),
    fun=mean, geom="line",
    inherit.aes=FALSE, aes(x=Time, y=Strength, linetype='dashed line'))

您需要应用group=美学,我认为您在longdata数据集中使用的组可能在这里不起作用... 或者可能会起作用,不确定。这就是为什么我建议在两个stat_summary调用中覆盖美学并为每个调用指定group=。如果绘制线条时出现问题,您可能需要为其中一个指定group=1,另一个指定group=2(我没有尝试过,因为我没有您的数据集)。关于在离散x轴上使用geom_line和有关group=美学的说明,请参见SO上此问题的答案

还要注意,我设置了fun=mean。我假设您正在绘制一条线段,该线段连接了您点集的均值...但您最好知道要绘制什么以确保映射正确的y值。


谢谢你的帮助。我正在努力修改它,因为我的x轴没有数字,所以我无法使用“x>5”等。我也不能创建一个新列,因为我必须将数据融合成长格式,使列成为不变的ID变量...情况变得更加复杂了:( - bbplot
抱歉我的格式不够好,顺便说一下,这是我的第一篇帖子。我很乐意上传我的数据框,但我不确定如何编辑帖子。 - bbplot
没问题。感谢@jpsmith的建议。请注意,我已编辑答案以“因素”(双关语)为考虑。 - chemdork123
非常感谢您,我无法表达我的感激之情!我仍然没有得到所需的虚线,但我觉得我已经接近了,可能只需要一些尝试。 - bbplot

1
基于@chemdork123的提议,但考虑到您的非数值X轴,您可以使用stat_summary(您还需要在aes()中添加group=1)。
library(ggplot2)
df <- data.frame(x=LETTERS[1:10], y=1:10)
ggplot(df, aes(x,y, group=1)) +
  stat_summary(data=subset(df,x %in% c("E","F","G","H","I","J")), fun.y=sum, geom="line", aes(linetype='solid line')) +
  stat_summary(data=subset(df,x %in% c("A","B","C","D","E")), fun.y=sum, geom="line", aes(linetype='dashed line'))

enter image description here


好建议! - chemdork123

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