如何用2个不同的y轴绘图?


122

我想在R中叠加两个散点图,以便每个点集都有其自己的(不同的)y轴(即,在图的位置2和4上),但这些点看起来重叠在同一图上。

有可能这样做plot吗?

编辑显示问题的示例代码

# example code for SO question
y1 <- rnorm(10, 100, 20)
y2 <- rnorm(10, 1, 1)
x <- 1:10
# in this plot y2 is plotted on what is clearly an inappropriate scale
plot(y1 ~ x, ylim = c(-1, 150))
points(y2 ~ x, pch = 2)

请提供样本数据。从美学的角度来看,这通常是一个坏主意。
大通

3
在以下特定情况下的答案和讨论ggplot2stackoverflow.com/questions/3099219/…(在SO [r] two y-axes或中搜索[r] twoord.plot)-还有其他一些相关答案,尽管(令我惊讶的是,这是一个R FAQ)并没有完全相同的答案
Ben Bolker

@chase-我添加了该问题的有效示例。感谢您就美学问题提出警告。
DQdlM 2011年

Answers:


126

更新:R Wiki上已复制的资料,网址为http://rwiki.sciviews.org/doku.php?id=tips:graphics-base:2yaxes,现在链接断开了:也可以从 Wayback机器上获得

同一图上的两个不同的y轴

(某些资料最初由Daniel Rajdl于2006/03/31 15:26发表)

请注意,在极少数情况下,在同一绘图上使用两个不同的比例是合适的。误导图形查看者很容易。请检查以下两个示例并对此问题进行评论(example1,来自Junk Charts的example2),以及Stephen Few的这篇文章(得出的结论是:“我当然不能一劳永逸地得出结论:双刻度轴的图永远不会有用;只是我无法根据其他更好的解决方案来考虑这种情况。”)另请参阅本动画片中的第4点...

如果确定的话,基本方法是创建您的第一个绘图,进行设置par(new=TRUE)以防止R清除图形设备,使用创建第二个绘图axes=FALSE(并设置xlabylab为空白– ann=FALSE应该也可以),然后使用axis(side=4)添加一个新轴在右侧,并在右侧mtext(...,side=4)添加轴标签。这是使用一些虚构数据的示例:

set.seed(101)
x <- 1:10
y <- rnorm(10)
## second data set on a very different scale
z <- runif(10, min=1000, max=10000) 
par(mar = c(5, 4, 4, 4) + 0.3)  # Leave space for z axis
plot(x, y) # first plot
par(new = TRUE)
plot(x, z, type = "l", axes = FALSE, bty = "n", xlab = "", ylab = "")
axis(side=4, at = pretty(range(z)))
mtext("z", side=4, line=3)

twoord.plot()plotrix包自动执行此过程,如同doubleYScale()latticeExtra软件包软件包一样。

另一个示例(改编自Robert W. Baer的R邮件列表帖子):

## set up some fake test data
time <- seq(0,72,12)
betagal.abs <- c(0.05,0.18,0.25,0.31,0.32,0.34,0.35)
cell.density <- c(0,1000,2000,3000,4000,5000,6000)

## add extra space to right margin of plot within frame
par(mar=c(5, 4, 4, 6) + 0.1)

## Plot first set of data and draw its axis
plot(time, betagal.abs, pch=16, axes=FALSE, ylim=c(0,1), xlab="", ylab="", 
   type="b",col="black", main="Mike's test data")
axis(2, ylim=c(0,1),col="black",las=1)  ## las=1 makes horizontal labels
mtext("Beta Gal Absorbance",side=2,line=2.5)
box()

## Allow a second plot on the same graph
par(new=TRUE)

## Plot the second plot and put axis scale on right
plot(time, cell.density, pch=15,  xlab="", ylab="", ylim=c(0,7000), 
    axes=FALSE, type="b", col="red")
## a little farther out (line=4) to make room for labels
mtext("Cell Density",side=4,col="red",line=4) 
axis(4, ylim=c(0,7000), col="red",col.axis="red",las=1)

## Draw the time axis
axis(1,pretty(range(time),10))
mtext("Time (Hours)",side=1,col="black",line=2.5)  

## Add Legend
legend("topleft",legend=c("Beta Gal","Cell Density"),
  text.col=c("black","red"),pch=c(16,15),col=c("black","red"))

在此处输入图片说明

相似的配方可用于叠加不同类型的图-条形图,直方图等。


这就是为什么仅链接的答案是一个坏主意的原因... wiki.r-project.org似乎已失效,我问r-devel@r-project.org。
Ben Bolker 2014年

@BenBolker您的解决方案真是天才!但是我有一个问题。如果两边都超过一条线,我仍然可以使用此方法,但只能使用符号。当我尝试使用line = plot时,它将尝试连续绘制它们。您是否会提出建议解决这个问题的技巧?
wthimdh

1
@BenBolker如果“时间”是类型为“ 2019-01-01”的日期格式,该怎么办。您将如何更改axis(1,pretty(range(time),10))线路?
k.dkhk

35

顾名思义,twoord.plot()plotrix程序包中,具有两个纵坐标轴的图。

library(plotrix)
example(twoord.plot)

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明


3
光滑 感谢卡车的例子。我也希望看到带有负值的线条和线条示例之一。另外堆叠会很好。
马特·班纳特

5

一种选择是并排绘制两个图。ggplot2为此提供了一个不错的选择facet_wrap()

dat <- data.frame(x = c(rnorm(100), rnorm(100, 10, 2))
  , y = c(rnorm(100), rlnorm(100, 9, 2))
  , index = rep(1:2, each = 100)
  )

require(ggplot2)
ggplot(dat, aes(x,y)) + 
geom_point() + 
facet_wrap(~ index, scales = "free_y")

4

如果可以放弃刻度/轴标签,则可以将数据重新缩放为(0,1)间隔。例如,当您通常对轨道之间的局部相关性感兴趣并且它们具有不同的比例(覆盖率成千上万,Fst 0-1)时,这适用于染色体上的不同“摆动” traks。

# rescale numeric vector into (0, 1) interval
# clip everything outside the range 
rescale <- function(vec, lims=range(vec), clip=c(0, 1)) {
  # find the coeficients of transforming linear equation
  # that maps the lims range to (0, 1)
  slope <- (1 - 0) / (lims[2] - lims[1])
  intercept <- - slope * lims[1]

  xformed <- slope * vec + intercept

  # do the clipping
  xformed[xformed < 0] <- clip[1]
  xformed[xformed > 1] <- clip[2]

  xformed
}

然后,将具有与数据帧chrompositioncoveragefst列,你可以这样做:

ggplot(d, aes(position)) + 
  geom_line(aes(y = rescale(fst))) + 
  geom_line(aes(y = rescale(coverage))) +
  facet_wrap(~chrom)

这样做的好处是您不仅限于两个traccs。


4

我也建议,twoord.stackplot()plotrix带有两个以上纵坐标轴的包装图中。

data<-read.table(text=
"e0AL fxAL e0CO fxCO e0BR fxBR anos
 51.8  5.9 50.6  6.8 51.0  6.2 1955
 54.7  5.9 55.2  6.8 53.5  6.2 1960
 57.1  6.0 57.9  6.8 55.9  6.2 1965
 59.1  5.6 60.1  6.2 57.9  5.4 1970
 61.2  5.1 61.8  5.0 59.8  4.7 1975
 63.4  4.5 64.0  4.3 61.8  4.3 1980
 65.4  3.9 66.9  3.7 63.5  3.8 1985
 67.3  3.4 68.0  3.2 65.5  3.1 1990
 69.1  3.0 68.7  3.0 67.5  2.6 1995
 70.9  2.8 70.3  2.8 69.5  2.5 2000
 72.4  2.5 71.7  2.6 71.1  2.3 2005
 73.3  2.3 72.9  2.5 72.1  1.9 2010
 74.3  2.2 73.8  2.4 73.2  1.8 2015
 75.2  2.0 74.6  2.3 74.2  1.7 2020
 76.0  2.0 75.4  2.2 75.2  1.6 2025
 76.8  1.9 76.2  2.1 76.1  1.6 2030
 77.6  1.9 76.9  2.1 77.1  1.6 2035
 78.4  1.9 77.6  2.0 77.9  1.7 2040
 79.1  1.8 78.3  1.9 78.7  1.7 2045
 79.8  1.8 79.0  1.9 79.5  1.7 2050
 80.5  1.8 79.7  1.9 80.3  1.7 2055
 81.1  1.8 80.3  1.8 80.9  1.8 2060
 81.7  1.8 80.9  1.8 81.6  1.8 2065
 82.3  1.8 81.4  1.8 82.2  1.8 2070
 82.8  1.8 82.0  1.7 82.8  1.8 2075
 83.3  1.8 82.5  1.7 83.4  1.9 2080
 83.8  1.8 83.0  1.7 83.9  1.9 2085
 84.3  1.9 83.5  1.8 84.4  1.9 2090
 84.7  1.9 83.9  1.8 84.9  1.9 2095
 85.1  1.9 84.3  1.8 85.4  1.9 2100", header=T)

require(plotrix)
twoord.stackplot(lx=data$anos, rx=data$anos, 
                 ldata=cbind(data$e0AL, data$e0BR, data$e0CO),
                 rdata=cbind(data$fxAL, data$fxBR, data$fxCO),
                 lcol=c("black","red", "blue"),
                 rcol=c("black","red", "blue"), 
                 ltype=c("l","o","b"),
                 rtype=c("l","o","b"), 
                 lylab="Años de Vida", rylab="Hijos x Mujer", 
                 xlab="Tiempo",
                 main="Mortalidad/Fecundidad:1950–2100",
                 border="grey80")
legend("bottomright", c(paste("Proy:", 
                      c("A. Latina", "Brasil", "Colombia"))), cex=1,
        col=c("black","red", "blue"), lwd=2, bty="n",  
        lty=c(1,1,2), pch=c(NA,1,1) )

1

与@BenBolker接受的答案类似的另一种替代方法是在添加第二组点时重新定义现有图的坐标。

这是一个最小的例子。

数据:

x  <- 1:10
y1 <- rnorm(10, 100, 20)
y2 <- rnorm(10, 1, 1)

情节:

par(mar=c(5,5,5,5)+0.1, las=1)

plot.new()
plot.window(xlim=range(x), ylim=range(y1))
points(x, y1, col="red", pch=19)
axis(1)
axis(2, col.axis="red")
box()

plot.window(xlim=range(x), ylim=range(y2))
points(x, y2, col="limegreen", pch=19)
axis(4, col.axis="limegreen")

例

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.