Làm cách nào để vẽ biểu đồ với 2 trục y khác nhau?


122

Tôi muốn chồng hai biểu đồ phân tán trong R sao cho mỗi tập hợp điểm có trục y (khác nhau) của riêng nó (tức là, ở vị trí 2 và 4 trên hình) nhưng các điểm xuất hiện chồng trên cùng một hình.

Có thể làm điều này với plot?

Chỉnh sửa mã ví dụ hiển thị sự cố

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

Vui lòng cung cấp dữ liệu mẫu. Nhìn chung đây là một ý tưởng tồi từ góc độ thẩm mỹ.
Đuổi theo

3
câu trả lời và thảo luận trong trường hợp cụ thể của ggplot2: stackoverflow.com/questions/3099219/… (tìm kiếm SO cho [r] two y-axeshoặc [r] twoord.plot) - có một vài câu trả lời liên quan khác, mặc dù (tôi ngạc nhiên vì đó là Câu hỏi thường gặp về R) không có gì giống nhau
Ben Bolker

@chase - Tôi đã thêm một ví dụ làm việc về sự cố. Cảm ơn đã cảnh báo về các vấn đề thẩm mỹ.
DQdlM

Câu trả lời:


126

cập nhật : Tài liệu được sao chép trên R wiki tại http://rwiki.sciviews.org/doku.php?id=tips:graphics-base:2yaxes , liên kết hiện đã bị hỏng: cũng có sẵn từ máy quay lui

Hai trục y khác nhau trên cùng một âm mưu

(một số tài liệu nguyên bản của Daniel Rajdl 2006/03/31 15:26)

Xin lưu ý rằng có rất ít trường hợp thích hợp sử dụng hai thang đo khác nhau trên cùng một cốt truyện. Nó rất dễ gây hiểu lầm cho người xem hình ảnh. Kiểm tra hai ví dụ sau và nhận xét về vấn đề này (ví dụ1 , ví dụ2 từ Biểu đồ rác ), cũng như bài viết này của Stephen Vài (kết luận "Tôi chắc chắn không thể kết luận, một lần và mãi mãi, rằng đồ thị có trục tỷ lệ kép không bao giờ hữu ích; chỉ là tôi không thể nghĩ ra một tình huống đảm bảo cho họ dựa trên các giải pháp khác tốt hơn. ”) Cũng xem điểm # 4 trong phim hoạt hình này ...

Nếu bạn quyết tâm, công thức cơ bản là tạo cốt truyện đầu tiên của bạn, đặt par(new=TRUE)để ngăn R xóa thiết bị đồ họa, tạo cốt truyện thứ hai với axes=FALSE(và đặt xlabylabđể trống - ann=FALSEcũng nên hoạt động) và sau đó sử dụng axis(side=4)để thêm một trục mới ở phía bên phải và mtext(...,side=4)để thêm nhãn trục ở phía bên phải. Dưới đây là một ví dụ sử dụng một chút dữ liệu được tạo sẵn:

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()trong plotrixgói tự động hóa quá trình này, cũng như doubleYScale()trong latticeExtragói.

Một ví dụ khác (phỏng theo bài đăng trong danh sách gửi thư R của Robert W. Baer):

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

nhập mô tả hình ảnh ở đây

Các công thức tương tự có thể được sử dụng để chồng các ô thuộc nhiều loại khác nhau - ô thanh, biểu đồ, v.v.


đây là lý do tại sao câu trả lời chỉ có liên kết là một ý tưởng tồi ... wiki.r-project.org xuất hiện không còn tồn tại, tôi đang hỏi trên r-devel@r-project.org.
Ben Bolker

@BenBolker giải pháp của bạn là thiên tài! tuy nhiên tôi có một câu hỏi. Nếu nó có nhiều hơn một dòng ở cả hai bên, tôi vẫn có thể sử dụng phương pháp này nhưng chỉ với các ký hiệu. Khi tôi cố gắng sử dụng line = plot, nó sẽ cố gắng vẽ chúng liên tục. Bạn có tình cờ đề xuất một mẹo để khắc phục điều này không?
wthimdh

1
@BenBolker Điều gì sẽ xảy ra nếu Thời gian là định dạng ngày của loại: "2019-01-01". Bạn sẽ thay đổi axis(1,pretty(range(time),10))dòng như thế nào?
k.dkhk

35

Như tên gọi của nó cho thấy, twoord.plot()trong gói ma trận đồ thị có hai trục tọa độ.

library(plotrix)
example(twoord.plot)

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây


3
bóng bẩy. cảm ơn vì các ví dụ về tải trọng xe tải. Tôi cũng muốn xem một trong những ví dụ về dòng và thanh có giá trị âm. Cũng nên xếp chồng lên nhau.
Matt Bannert

5

Một lựa chọn là tạo hai ô cạnh nhau. ggplot2cung cấp một tùy chọn tốt cho việc này với 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

Nếu bạn có thể từ bỏ nhãn tỷ lệ / trục, bạn có thể chia tỷ lệ dữ liệu thành (0, 1) khoảng thời gian. Ví dụ, điều này hoạt động đối với các đường mòn 'lung lay' khác nhau trên nhiễm sắc thể, khi bạn thường quan tâm đến các mối tương quan cục bộ giữa các đường và chúng có các quy mô khác nhau (phạm vi bao phủ hàng nghìn, Fst 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
}

Sau đó, có một khung dữ liệu với chrom, position, coveragefstcác cột, bạn có thể làm như sau:

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

Ưu điểm của việc này là bạn không bị giới hạn ở hai xe điện.


4

Tôi cũng gợi ý, twoord.stackplot()trong các plotrixlô gói có nhiều hơn hai trục tọa độ.

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

Một phương án khác tương tự như câu trả lời được chấp nhận bởi @BenBolker là xác định lại tọa độ của ô hiện có khi thêm tập hợp điểm thứ hai.

Đây là một ví dụ tối thiểu.

Dữ liệu:

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

Âm mưu:

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

thí dụ

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.