有没有办法在R图中对齐2个独立的轴?

时间:2016-06-30 21:22:18

标签: r plot axis

我正在绘制一个不同轴的图形。问题是我希望2个轴穿过一个点,其余的并不重要。有可能吗?

这是一个可重现的代码:

plot(x = -10:10, y = -10:10)
abline(v=0,lty = 2)
par(new =TRUE)
plot(x = -10:50, y = seq(-5,5,length.out = length(-10:50)), xaxt = "n", yaxt = "n", bty ="n")
abline(v=0,lty = 3)
axis(3, col="red",col.axis="red",las=2, cex.axis = 1)
axis(4, col="red",col.axis="red",las=2, cex.axis = 1)

这是输出: enter image description here

我基本上希望垂直线在0处相互交叉。

还有另一种方式来写这个(这不是很准确,我想要一些可以自动完成的东西,而不是手动设置xlim,因为我有很多要做的事情。此外,当图像被调整大小,失去与2 0的对齐):

plot(x = -10:10, y = -10:10)
abline(v=0,lty = 2)
par(new =TRUE)
plot(x = -10:50, y = seq(-5,5,length.out = length(-10:50)), 
     xaxt = "n", yaxt = "n", bty ="n",
     xlim = c(-50,50))
abline(v=0,lty = 3, lwd = 5)
axis(3, col="red",col.axis="red",las=2, cex.axis = 1)
axis(4, col="red",col.axis="red",las=2, cex.axis = 1)

enter image description here

输出应该使用类似于biplot.prcomp用来对齐箭头和轴的东西: enter image description here

EDITED

使用PCA时,它仅适用于y轴,而不适用于x轴。

new_lim <- function(a, type = 1) {
  newdata_ratio <-  NULL
  i <- type * 2 - 1
  old_lim <- par("usr")[i:(i+1)] + c(diff(par("usr")[i:(i+1)]) * 0.04 / 1.08, 
                                     diff(par("usr")[i:(i+1)]) * -0.04 / 1.08)
  old_ratio <- old_lim[1] / old_lim[2]
  newdata_ratio <- if (max(a) <= 0) -1.0e+6 else min(a) / max(a)
  if (old_ratio >= newdata_ratio ) {
    new_min <- min(a)
    new_max <- min(a) / old_ratio
  } else {
    new_min <- max(a) * old_ratio
    new_max <- max(a)
  }
  c(new_min, new_max)
}
s1= rnorm(50,mean = 12)
s2= rnorm(50, mean = 17)
s3= rnorm(50, mean = 20)
library(vegan)
pca=rda(cbind(s1,s2,s3))
pca.scoop=scores(pca, scaling = 2)
biplot(pca)

par(mar=c(4, 4, 4, 4))
plot(pca, xlab = "x1", ylab = "y1",
     type = c("p"),
     main= "main",
     scaling = 2,
     choices = c(1,2),
     xlim =c(min(pca.scoop$sites[,1]),max(pca.scoop$sites[,1])),
     ylim = c(min(pca.scoop$sites[,2]),max(pca.scoop$sites[,2])),
     bty = "o",#"l"
     pch=4)
abline(v = 0, lty = 2); abline(h = 0, lty = 2)

x2 <- -10:20
y2 <- seq(40, 10, length.out = length(x2))
par(new =TRUE)
plot(x2, y2, 
     xlim = new_lim(x2), 
     ylim = new_lim(y2, 2), axes = F, ann = F)
axis(3, col = "red", col.axis = "red") # axes=F is equivalent to xaxt="n", yaxt="n" and bty="n"
axis(4, col = "red", col.axis = "red") # ann=F is equivalent to xlab=NA and ylab=NA
mtext("x2", side = 3, line = 2.5, col = "red")
mtext("y2", side = 4, line = 2.5, col = "red")
# box(bty="7", col="red")  # if you want.

enter image description here

2 个答案:

答案 0 :(得分:1)

这不是一个漂亮的解决方案,但只要你的x轴总是超过0值,你就可以为这两个图设置xlim=c(-max(c(-min(x),max(x))),max(c(-min(x),max(x))))。这将使x轴始终以0为中心,用于顶轴和底轴。如果您愿意,可以使用y轴完成相同的操作。

# Set graphing parameters
par(mar = c(5,4,4,4) + 0.1) # This can be reset later with "dev.off()"

# Plot the first graph
plot(x = -10:10, y = -10:10, 
     xlim=c(-max(c(-min(x),max(x))),max(c(-min(x),max(x)))),
     xlab="x-label-1",ylab="y-label-1") # Added labels to be changed
abline(v=0,lty = 2)

# Plot the second graph using new axes
par(new =TRUE)
plot(x = -10:50, y = seq(-5,5,length.out = length(-10:50)), 
     xaxt = "n", yaxt = "n", bty ="n",
     xlim=c(-max(c(-min(x),max(x))),max(c(-min(x),max(x)))),
     xlab=NA,ylab=NA) # Remove x- and y-axis labels
abline(v=0,lty = 3)
axis(3, col="red",col.axis="red",las=2, cex.axis = 1)
axis(4, col="red",col.axis="red",las=2, cex.axis = 1)
mtext("x-label-2", side = 3, line = 3, cex = par("cex.lab")) # Labeled secondary x-axis
mtext("y-label-2", side = 4, line = 3, cex = par("cex.lab")) # Labeled secondary y-axis

给出:

enter image description here

我希望这有效!如果您想使用标题标记图表,则需要使用par(mar())的值。

答案 1 :(得分:1)

  

是否可以根据第一张图对齐第二张图?

是的,确实如此。但由于需要合乎逻辑的判断,这是一个复杂的情结。

此功能new_lim(a, type)计算第一个图形的xlim(或ylim)以及图形参数的减号与加号的比率。并且它判断它使用哪个值作为第二个图形的参数,min(第二个数据)或max,并从第一个图形的比率计算另一个值。输出是第二个图形的最小值和最大值_lim。参数a是第二个x或y数据。 type = 1(默认值;省略)适用于xlimtype = 2type =可省略)适用于ylim

new_lim <- function(a, type = 1) {
  newdata_ratio <-  NULL
  i <- type * 2 - 1
  old_lim <- par("usr")[i:(i+1)] + c(diff(par("usr")[i:(i+1)]) * 0.04 / 1.08, 
                                     diff(par("usr")[i:(i+1)]) * -0.04 / 1.08)
  old_ratio <- old_lim[1] / old_lim[2]
  newdata_ratio <- if (max(a) <= 0) -1.0e+6 else min(a) / max(a)
  if (old_ratio >= newdata_ratio ) {
    new_min <- min(a)
    new_max <- min(a) / old_ratio
  } else {
    new_min <- max(a) * old_ratio
    new_max <- max(a)
  }
  c(new_min, new_max)
}

[注] 该功能需要存在于第一个图形中,并且包括第一个数据范围的零。第二个数据的范围不包括零是没有问题的。

x2 <- -40:20
y2 <- seq(40, 10, length.out = length(-40:20))

par(mar=c(4, 4, 4, 4))
plot(x = -15:5, y = -5:15, xlab = "x1", ylab = "y1")
abline(v = 0, lty = 2); abline(h = 0, lty = 2)

par(new =TRUE)
plot(x2, y2, xlim = new_lim(x2), ylim = new_lim(y2, 2), axes = F, ann = F)
axis(3, col = "red", col.axis = "red") # axes=F is equivalent to xaxt="n", yaxt="n" and bty="n"
axis(4, col = "red", col.axis = "red") # ann=F is equivalent to xlab=NA and ylab=NA
mtext("x2", side = 3, line = 2.5, col = "red")
mtext("y2", side = 4, line = 2.5, col = "red")
# box(bty="7", col="red")  # if you want.

enter image description here

已编辑[注意]

当您使用此函数与plot(class.rda)并通过Rsutdio更改方面时,输出将与您想要的不同。

x2 <- -10:20
y2 <- seq(40, 10, length.out = length(x2))
library(vegan) 
s1= rnorm(50,mean = 12); s2= rnorm(50, mean = 17); s3= rnorm(50, mean = 20)
pca=rda(cbind(s1,s2,s3))
pca.scoop=scores(pca, scaling = 2)
biplot(pca)
par(new =TRUE)
plot(x2, y2, 
     xlim = new_lim(x2), 
     ylim = new_lim(y2, 2), axes = F, ann = F)
axis(3, col = "red", col.axis = "red")
axis(4, col = "red", col.axis = "red")
mtext("x2", side = 3, line = 2, col = "red")
mtext("y2", side = 4, line = 2, col = "red")

enter image description here