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)

샘플 데이터를 제공하십시오. 이것은 일반적으로 미학적 관점에서 나쁜 생각입니다.
Chase

3
특정 경우에 대한 답변 및 토론 ggplot2: stackoverflow.com/questions/3099219/… (SO 검색 [r] two y-axes또는 [r] twoord.plot)-몇 가지 다른 관련 답변이 있지만 (R FAQ이기 때문에 놀랍게도) 동일한 것은 없습니다
Ben Bolker

@chase-문제의 작동 예를 추가했습니다. 미적 문제에 대한 경고에 감사드립니다.
DQdlM

답변:


126

업데이트 : http://rwiki.sciviews.org/doku.php?id=tips:graphics-base:2yaxes 의 R 위키에 있던 복사 된 자료 , 이제 링크가 끊어졌습니다. 웨이 백 머신 에서도 사용 가능

동일한 플롯에있는 두 개의 서로 다른 y 축

(원래 Daniel Rajdl의 일부 자료 2006/03/31 15:26)

동일한 플롯에서 두 개의 다른 척도를 사용하는 것이 적절한 상황은 거의 없습니다. 그래픽을 보는 사람을 오도하는 것은 매우 쉽습니다. 이 문제에 대한 다음 두 가지 예와 주석 (예 : 정크 차트의 example1 , 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
멋진. 예제의 트럭 부하에 감사드립니다. 음수 값을 가진 선 및 막대 예제 중 하나를보고 싶습니다. 스태킹도 좋을 것입니다.
Matt Bannert 2016

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) 간격으로 다시 스케일링 할 수 있습니다. 이것은 예를 들어, 당신이 일반적으로 트랙들 사이의 국소 적 상관 관계에 관심이 있고 다른 척도를 가지고있을 때 염색체의 다른 '흔들림'트랙에 대해 작동합니다.

# 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
}

그런 다음에 데이터 프레임을 갖는 chrom, position, coveragefst열을, 당신이 뭔가를 같이 할 수 있습니다 :

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

이것의 장점은 두 개의 트랙에 국한되지 않는다는 것입니다.


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")

예

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.