问题
I am trying to build some figures comprised to 2 right triangles arranged in a mirror-image of each other. The final plots will have unique data set, but for now I am plotting the same data. I am more familiar with (maybe spoiled by) ggplot, but I've found that it's much easier to shift the axis locations in base R. If anyone knows how to replicate these right-triangle plots in ggplot I would take that answer!
I'm having trouble with adjusting the spacing and layout. I'm not as familiar with base R plotting, sorry if these are kinda of basic.
Specifically I'd like to:
move the triangles closer together
make it so the labels are visible (and use a top label that isn't
**main**
)make the diagonal line flush with the axes
make the 'legs' of the triangles of equal length
library(cowplot) my.data <- data.frame( my.x = c(.2,.4,.6, .1), my.y = c(.3, .5, .7, .9) ) top.triangle <- function(){ plot( my.y ~ my.x, data = my.data, axes = FALSE, ylab = 'Position.2', xlab = NA, main='Position.1', xlim=c(0,1), ylim=c(0,1), xaxt="n", yaxt="n" ) axis(side = 2, las = 1, pos=0) axis(side = 3, las = 1, pos=1) abline(coef = c(0,1)) } bottom.triangle <- function() { plot( my.x ~ my.y, data = my.data , axes = FALSE, xlab = 'Position.2', ylab = 'Position.1', xlim=c(0,1), ylim=c(0,1), xaxt="n", yaxt="n" ) axis(side = 1, las = 1, pos=0) axis(4, las = 1, pos=1) #flip label to right side abline(coef = c(0,1))} plot_grid(top.triangle, bottom.triangle, rel_widths = c(.5,.5))
Thanks!
回答1:
As @GregorThomas suggested, it's probably better to draw a single plot. For this, a transform
ed additional data frame is needed, that shifts the values by an distance x.dist
.
my.data <- data.frame(my.x=c(.2, .4, .6, .1), my.y=c(.3, .5, .7, .9))
x.dist <- .5
my.data.2 <- transform(my.data, my.y=my.y + x.dist)
Now I've modified your functions substantially, I suggest to figure out line by line which arguments I've used. Importantly I use xpd=TRUE
to be able to plot beyond the plot region. With par
I expand the mar
gins a little. I use mtext
together with axis
to get tickmarks and labels. To make diagonal line flush with the axes I used lines
instead of abline
. The bottom.triangle2 now uses points
rather than plot
, because plot
has no add=TRUE
argument. And I use asp=1
in top.triangle2
to make equilateral triangles.
top.triangle2 <- function() {
plot(my.y ~ my.x, data= my.data, axes=FALSE, ylab='', xlab="",
main='', xlim=c(0, 1), ylim=c(0, 1), xaxt="n", yaxt="n", asp=1)
mtext("Here could be your title", 3, 5, font=2, cex=1.3, adj=.95)
mtext("Position.2", 2, .75)
mtext("Position.1", 3, 2)
axis(side=2, las=1, pos=0)
axis(side=3, las=1, pos=1)
lines(0:1, 0:1)
}
bottom.triangle2 <- function() {
points(my.x ~ my.y, data=my.data.2, xpd=TRUE)
mtext("Position.2", 1, 1.5, at=mean(par()$usr[1:2]) + x.dist)
mtext("Position.1", 4, 3, padj=par()$usr[1] + 10)
x.at <- axisTicks(par()$usr[1:2], 0) + x.dist
axis(side=1, las=1, pos=0, at=x.at,
labels=F, xpd=TRUE)
mtext(seq(0, 1, .2), 1, 0, at=x.at)
axis(4, las=1, pos=1 + x.dist)
lines(0:1 + x.dist, 0:1, xpd=TRUE)
}
I use png
to get reproducible output.
png("myplot.png", width=650, height=500)
op <- par(mar=c(3, 4, 8, 12) + 0.1, oma=c(2, 0, 0, 2))
top.triangle2()
bottom.triangle2()
par(op)
dev.off()
Result
Maybe you figure out on your own how to avoid that much hard coding.
来源:https://stackoverflow.com/questions/61378161/r-base-plot-combine-mirrored-right-triangles