在同一张图中绘制两个图表

687

我想在同一张图中绘制y1和y2。

x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x, 1, 1)
plot(x, y1, type = "l", col = "red")
plot(x, y2, type = "l", col = "green")

但是当我这样做时,它们没有在同一张图中绘制。

在Matlab中,可以使用hold on实现此功能,但是有人知道如何在R中实现吗?


5
查看?curve。使用参数add=TRUE - isomorphismes
请参考这个问题获取更具体的ggplot2答案。 - Axeman
17个回答

722

lines()points()会添加到现有的图形中,但不会创建一个新窗口。因此,您需要执行下面的操作:

plot(x,y1,type="l",col="red")
lines(x,y2,col="green")

12
为什么在下面这个简单的例子中无法工作?
plot(sin) lines(cos) as.double(y)的错误: 无法将'type'内置类型强制转换为'double'类型的向量
- Frank
26
很容易理解,使用plot(sin)时,你传递的是一个函数而不是实际数据。plot()函数会检测到这一点,并使用plot.function()函数绘制你的函数(如果想了解更多,可以了解一下多重派发)。然而,lines.function()函数没有定义,因此lines()函数不知道如何处理类函数的参数。lines()函数只能处理属于类ts的数据和时间序列对象。 - Soumendra
37
像这样做:plot(sin); curve(cos, add=TRUE) - isomorphismes
2
如何在 x 不同的情况下使用相同的内容?比如,我有一个图表的 x1 和 y1,并在同一张图表上添加了另一个 x2 和 y2 的图表。x1 和 x2 都有相同的范围,但不同的值。 - Kavipriya
3
如何在这个图表中添加图例最简单? - hertzsprung
显示剩余4条评论

257

你也可以使用 par 在同一图表上但不同轴上绘制。如下所示:

plot( x, y1, type="l", col="red" )
par(new=TRUE)
plot( x, y2, type="l", col="green" )

如果你仔细阅读关于R中的par的资料,你将能够生成非常有趣的图形。另一本值得一看的书是Paul Murrel的R Graphics。


3
我的R出错了: Error in par(fig(new = TRUE)) : 找不到 "fig" 函数。 - Alessandro Jacopson
8
您的方法是否保留了两个图的正确纵轴比例(y轴比例)? - Alessandro Jacopson
1
@uvts_cvs 是的,它完整地保留了原始图形。 - Sam
15
问题在于这将重写几个情节要素。我会在第二个“plot”中包括“xlab =“”,ylab =“”,...”和其他一些要素。 - isomorphismes
如果你有时间的话,能否请你看一下我的问题?https://stackoverflow.com/questions/65650991/r-overlaying-points-on-a-graph 谢谢。 - stats_noob

145

在构建多层图时,应考虑使用ggplot包。这个想法是创建一个具有基本美学的图形对象,并逐步增强它。

ggplot风格要求数据被打包进data.frame中。

# Data generation
x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x,1,1)
df <- data.frame(x,y1,y2)

基本解决方案:

require(ggplot2)

ggplot(df, aes(x)) +                    # basic graphical object
  geom_line(aes(y=y1), colour="red") +  # first layer
  geom_line(aes(y=y2), colour="green")  # second layer

这里使用+运算符来向基本对象添加额外的层。

使用ggplot时,您可以在绘图的每个阶段访问图形对象。例如,通常的逐步设置可能如下所示:

g <- ggplot(df, aes(x))
g <- g + geom_line(aes(y=y1), colour="red")
g <- g + geom_line(aes(y=y2), colour="green")
g

g生成图表,您可以在每个阶段都看到它(好吧,在至少创建一个层之后)。还可以使用创建的对象进一步增强图表。例如,我们可以为轴添加标签:

g <- g + ylab("Y") + xlab("X")
g

最终的 g 看起来像这样:

图片描述

更新(2013-11-08):

如评论中指出,ggplot 的理念建议使用长格式的数据。 您可以参考这个答案以查看相应的代码。


5
正如 Henrik 建议的,数据应该采用“长”格式,这比您使用的“宽”格式更自然地处理了 ggplot - krlmlr
1
@Henrik:不,谢谢你首先回答我的问题。也许这个答案的作者可以编辑一下,使其更符合ggplot的理念... - krlmlr
3
你教我如何在ggplot的aes()中定义x,然后单独在geom_*()中定义y。不错! - Dan

61

我认为你正在寻找的答案是:

plot(first thing to plot)
plot(second thing to plot,add=TRUE)

38
似乎这个方法不起作用,它会出现“"add" is not a graphical parameter”警告信息,然后将第二幅图形打印在第一幅图形上。 - Waldir Leoncio
8
@WaldirLeoncio 请访问 https://dev59.com/Qmw15IYBdhLWcg3wJ4ms。 - Alessandro Jacopson
这样做的一个好处是似乎可以保持轴限制和标题的一致性。之前的一些方法会导致R在y轴上绘制两组刻度线,除非你费心指定更多的选项。不用说,轴上有两组刻度线可能会非常误导人。 - RMurphy
3
在 R 中,add 参数适用于某些绘图方法,但不适用于基本/默认的绘图方法。 - cloudscomputes
5
我遇到了相同的错误信息:“add”不是图形参数。我的R版本是R 3.2.3(2015-12-10)。您可以在这些绘图之间使用“par(new=TRUE)”命令。 - quepas

40

使用matplot函数:

matplot(x, cbind(y1,y2),type="l",col=c("red","green"),lty=c(1,1))

如果y1y2在相同的x点被评估,请使用此选项。它将Y轴缩放以适应较大的那个(y1y2),与其他答案不同,如果y2y1大,它们会夹断y2(ggplot解决方案大多可以接受这种情况)。

或者,如果两条线没有相同的x坐标,请在第一个图中设置轴限制,然后添加:

x1  <- seq(-2, 2, 0.05)
x2  <- seq(-3, 3, 0.05)
y1 <- pnorm(x1)
y2 <- pnorm(x2,1,1)

plot(x1,y1,ylim=range(c(y1,y2)),xlim=range(c(x1,x2)), type="l",col="red")
lines(x2,y2,col="green")

我很惊讶这个问题已经存在4年了,竟然没有人提到matplotx/ylim...


这里的range()函数特别有用。 - JASC

34

简而言之:您想使用curve(带有add=TRUE)或lines


我不同意使用par(new=TRUE),因为这会导致刻度线和轴标签重复打印。例如:

sine and parabola

plot(sin); par(new=T); plot( function(x) x**2 )的输出结果。

看看垂直轴标签是多么混乱!由于范围不同,您需要设置ylim=c(两个函数之间最低点, 两个函数之间最高点),这比我将要向您展示的方式更加困难——如果您想添加不止两条曲线,那就更加困难了。


让我困惑的一点是绘图中curvelines之间的区别。(如果您记不住这两个重要的绘图命令的名称,可以唱出来。)

curvelines之间的主要区别在于:

curve会绘制一个函数,例如curve(sin)。而lines则绘制具有x和y值的点,例如:lines( x=0:10, y=sin(0:10) )

这里还有一个小区别:对于您要做的事情,curve需要使用add=TRUE进行调用,而lines则默认假定您正在添加到现有的绘图中。

id & sine

这是调用plot(0:2); curve(sin)的结果。


在幕后,查看一下methods(plot)。并且检查body( plot.function )[[5]]。当您调用plot(sin)时,R会发现sin是一个函数(而不是y值),然后使用plot.function方法,最终调用curve。因此,curve是处理函数的工具。


27

如果你想将图形分成两列(即两个相邻的图形),可以像这样做:

par(mfrow=c(1,2))

plot(x)

plot(y) 

参考链接


23

根据 @redmode 的描述,您可以使用 ggplot 在同一图形设备中绘制这两行。在那个答案中,数据格式是“宽”的。然而,使用 ggplot 时,通常最方便的方法是将数据保留在数据框中的“长”格式。然后,通过在 aes 主题参数中使用不同的“分组变量”,线的属性(例如线型或颜色)将根据分组变量而变化,并相应的图例将出现。

在这种情况下,我们可以使用color主题参数,将线的颜色与数据集中一个变量的不同水平相匹配(此处为 y1 vs y2)。但首先,我们需要使用例如来自 reshape2 包的函数 'melt' 将数据从宽转换为长格式。有关重塑数据的其他方法在此处描述:Reshaping data.frame from wide to long format

library(ggplot2)
library(reshape2)

# original data in a 'wide' format
x  <- seq(-2, 2, 0.05)
y1 <- pnorm(x)
y2 <- pnorm(x, 1, 1)
df <- data.frame(x, y1, y2)

# melt the data to a long format
df2 <- melt(data = df, id.vars = "x")

# plot, using the aesthetics argument 'colour'
ggplot(data = df2, aes(x = x, y = value, colour = variable)) + geom_line()

在此输入图片描述


18

你可以使用数据点进行覆盖绘图。

plot(x1, y1,col='red')

points(x2,y2,col='blue')

18

如果你使用的是基础图形(即非格子/网格图形),那么你可以通过使用点/线/多边形函数向绘图中添加其他细节而不启动新绘图来模仿MATLAB的hold on功能。在多图布局的情况下,你可以使用par(mfg=...)选择添加元素的图。


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