【问题标题】:Plot two graphs in same plot in R在 R 中的同一图中绘制两个图
【发布时间】:2011-02-03 14:08:44
【问题描述】:

我想在同一个图中绘制 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 中做到这一点吗?

【问题讨论】:

  • 查看?curve。使用add=TRUE
  • 查看 this question 以获得更具体的 ggplot2 答案。

标签: r plot ggplot2 r-faq


【解决方案1】:

在构建多层地块时,应考虑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

这里+ operator用于为基本对象添加额外的层。

使用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):

正如 cmets 所指出的,ggplot 的理念建议使用长格式数据。 你可以参考这个answer来查看对应的代码。

【讨论】:

  • 作为suggested by Henrik,数据确实应该是“长”格式,ggplot 比您使用的“宽”格式更自然地处理这一点。
  • @Henrik:不,首先感谢您的回答。也许此答案的作者可以对其进行编辑,使其与ggplot 的理念非常吻合...
  • 教我在 ggplot(aes()) 上定义 x,然后在 geom_*() 上单独定义 y。不错!
【解决方案2】:

如果你想把绘图分成两列(2 个并排),你可以这样做:

par(mfrow=c(1,2))

plot(x)

plot(y) 

Reference Link

【讨论】:

    【解决方案3】:

    使用plotly(从plotly 添加带有主要和次要y 轴的解决方案- 似乎丢失了):

    library(plotly)     
    x  <- seq(-2, 2, 0.05)
    y1 <- pnorm(x)
    y2 <- pnorm(x, 1, 1)
    
    df=cbind.data.frame(x,y1,y2)
    
      plot_ly(df) %>%
        add_trace(x=~x,y=~y1,name = 'Line 1',type = 'scatter',mode = 'lines+markers',connectgaps = TRUE) %>%
        add_trace(x=~x,y=~y2,name = 'Line 2',type = 'scatter',mode = 'lines+markers',connectgaps = TRUE,yaxis = "y2") %>%
        layout(title = 'Title',
           xaxis = list(title = "X-axis title"),
           yaxis2 = list(side = 'right', overlaying = "y", title = 'secondary y axis', showgrid = FALSE, zeroline = FALSE))
    

    工作演示的屏幕截图:

    【讨论】:

    • 我编译了代码不行,先在%>%中标记了错误然后我删除了,然后又标记了错误Error in library(plotly) : there is no package called ‘plotly’为什么?
    • 你安装包plotly了吗?您需要使用install.packages("plotly") 命令安装软件包。
    【解决方案4】:

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

    在这种情况下,我们可以使用colour 美学,它将线条的颜色与数据集中变量的不同级别相匹配(这里:y1 vs y2)。但首先我们需要将数据从宽格式转换为长格式,例如使用reshape2 包中的“融化”功能。此处描述了重塑数据的其他方法: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()
    

    【讨论】:

      【解决方案5】:

      您可以使用 plotly 包中的 ggplotly() 函数将此处的任何 gggplot2 示例转换为交互式绘图,但我认为这种绘图是没有 ggplot2 更好:

      # call Plotly and enter username and key
      library(plotly)
      x  <- seq(-2, 2, 0.05)
      y1 <- pnorm(x)
      y2 <- pnorm(x, 1, 1)
      
      plot_ly(x = x) %>%
        add_lines(y = y1, color = I("red"), name = "Red") %>%
        add_lines(y = y2, color = I("green"), name = "Green")
      

      【讨论】:

      • 情节看起来很棒;是免费的吗?
      • @denis,有无限的免费公共绘图和付费私人绘图或内部选项。请参阅plans page
      • plotly R 包现在是 100% 免费和开源的(MIT 许可)。您可以在有或没有情节帐户的情况下使用它。
      • 你能看看我的问题吗? stackoverflow.com/questions/65650991/… 谢谢!
      【解决方案6】:

      我们也可以使用 lattice 库

      library(lattice)
      x <- seq(-2,2,0.05)
      y1 <- pnorm(x)
      y2 <- pnorm(x,1,1)
      xyplot(y1 + y2 ~ x, ylab = "y1 and y2", type = "l", auto.key = list(points = FALSE,lines = TRUE))
      

      特定颜色

      xyplot(y1 + y2 ~ x,ylab = "y1 and y2", type = "l", auto.key = list(points = F,lines = T), par.settings = list(superpose.line = list(col = c("red","green"))))
      

      【讨论】:

        【解决方案7】:

        惯用的 Matlab plot(x1,y1,x2,y2) 可以用 ggplot2 在 R 中翻译,例如:

        x1 <- seq(1,10,.2)
        df1 <- data.frame(x=x1,y=log(x1),type="Log")
        x2 <- seq(1,10)
        df2 <- data.frame(x=x2,y=cumsum(1/x2),type="Harmonic")
        
        df <- rbind(df1,df2)
        
        library(ggplot2)
        ggplot(df)+geom_line(aes(x,y,colour=type))
        

        灵感来自赵婷婷的Dual line plots with different range of x-axis Using ggplot2

        【讨论】:

          【解决方案8】:

          您也可以使用ggvis 创建情节:

          library(ggvis)
          
          x  <- seq(-2, 2, 0.05)
          y1 <- pnorm(x)
          y2 <- pnorm(x,1,1)
          df <- data.frame(x, y1, y2)
          
          df %>%
            ggvis(~x, ~y1, stroke := 'red') %>%
            layer_paths() %>%
            layer_paths(data = df, x = ~x, y = ~y2, stroke := 'blue')
          

          这将创建以下情节:

          【讨论】:

            【解决方案9】:

            tl;dr:您想使用curve(与add=TRUE)或lines


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

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

            看看垂直轴标签是多么混乱!由于范围不同,您需要设置 ylim=c(lowest point between the two functions, highest point between the two functions),这比我将要向您展示的要容易 - 如果您想添加的不仅仅是两条曲线,方式也不太容易,但很多。


            我一直对绘图感到困惑的是curvelines 之间的区别。 (如果您不记得这些是两个重要绘图命令的名称,只需 sing 即可。)

            这是curvelines 之间的最大区别。

            curve 将绘制一个函数,例如curve(sin)lines 用 x 和 y 值绘制点,例如:lines( x=0:10, y=sin(0:10) )

            这里有一个小的区别:curve 需要用 add=TRUE 调用,而lines 已经假定你正在添加到现有的情节。

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


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

            【讨论】:

              【解决方案10】:

              使用matplot函数:

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

              如果y1y2 在相同的x 点进行评估,请使用此选项。它缩放 Y 轴以适应较大的一个(y1y2),这与此处的其他一些答案不同,如果它大于 y1(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")
              

              我很惊讶这个 Q 已经 4 岁了,没有人提到 matplotx/ylim...

              【讨论】:

              • 这里的range()函数特别有用。
              【解决方案11】:

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

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

              【讨论】:

              • 这似乎不起作用,它给出了一个"add" is not a graphical parameter 警告,然后只在第一个图上打印第二个图。
              • 这样做的一个很好的好处是它似乎保持轴限制和标题一致。前面的一些方法会导致 R 在 y 轴上绘制两组刻度线,除非您遇到指定更多选项的麻烦。不用说,在坐标轴上有两组刻度线可能会产生误导。
              • add 参数适用于某些绘图方法,但不适用于 R 中的基本/默认方法
              • 我遇到了同样的错误"add" is not a graphical parameter。我的 R 是R version 3.2.3 (2015-12-10)。您可以在这些图之间使用par(new=TRUE) 命令。
              【解决方案12】:

              您也可以使用par 并在同一图表上绘制不同的轴。如下:

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

              如果您详细阅读R 中的par,您将能够生成非常有趣的图表。另一本书是 Paul Murrel 的 R Graphics。

              【讨论】:

              • 我的 R 给我一个错误:par(fig(new = TRUE)) 中的错误:找不到函数“fig”
              • 您的方法是否保留了两个图的正确比例(y 轴)?
              • @uvts_cvs 是的,它保留了原图。
              • 这样做的问题是它会重写几个情节元素。我会在第二个plot 中包含xlab="", ylab="", ... 和其他一些人。
              • 如果你有时间可以看看我的问题吗? stackoverflow.com/questions/65650991/… 谢谢
              【解决方案13】:

              您可以使用点作为重叠图。

              plot(x1, y1,col='red')
              
              points(x2,y2,col='blue')
              

              【讨论】:

                【解决方案14】:

                不要将要绘制的值保存在数组中,而是将它们存储在矩阵中。默认情况下,整个矩阵将被视为一个数据集。但是,如果您在绘图中添加相同数量的修饰符,例如col(),因为你在矩阵中有行,R 会发现每一行都应该被独立处理。例如:

                x = matrix( c(21,50,80,41), nrow=2 )
                y = matrix( c(1,2,1,2), nrow=2 )
                plot(x, y, col("red","blue")
                

                这应该可以工作,除非您的数据集大小不同。

                【讨论】:

                • 这给出: if (as.factor) { 中的错误:参数不可解释为逻辑
                【解决方案15】:

                如果您使用的是基本图形(即不是晶格/网格图形),那么您可以通过使用点/线/多边形函数来模拟 MATLAB 的保持功能,从而在不开始新绘图的情况下为绘图添加更多细节。在多情节布局的情况下,您可以使用par(mfg=...) 来选择要添加内容的情节。

                【讨论】:

                  【解决方案16】:

                  lines()points() 将添加到现有图表,但不会创建新窗口。所以你需要这样做

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

                  【讨论】:

                  • 为什么在下面的简单示例中不起作用? > plot(sin) > lines(cos) as.double(y) 中的错误:无法将“builtin”类型强制转换为“double”类型的向量
                  • 这很容易看到。使用 plot(sin),您传递的是函数而不是实际数据。 plot() 将检测到这一点,然后使用 plot.function() 来绘制你的函数(阅读多次调度以了解更多信息)。但是,lines.function() 没有定义,所以lines() 不知道如何处理类函数的参数。 lines 只能处理您的数据和 ts 类的时间序列对象。
                  • @Frank 这样做:plot(sin); curve(cos, add=TRUE).
                  • x不一样怎么用?比如说,我有一个图表的 x1 和 y1,并在同一个图表中添加另一个 x2 和 y2 的图表。 x1 和 x2 的范围相同,但值不同。
                  • 向其中添加图例最直接的方法是什么?
                  猜你喜欢
                  • 1970-01-01
                  • 2013-10-03
                  • 1970-01-01
                  • 2015-12-06
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多