3

I am working in RStudio and trying to make a 3x3 grid of the triangle plots built with the functions below. I’ve included a reproducible example, and the error I am running into is that the margins are too large to plot multiple plot, even though I am reducing the width and height. I’ve also tried saving these as png and loading them in to arrange with cowplot, but the figure is very blurry and I’m not sure how to adjust the text size or line thickness to make the figures more legible.

 #Data
iris$nrm.Sepal <- iris$Sepal.Width / iris$Sepal.Length
iris$nrm.Petal <- iris$Petal.Width / iris$Petal.Length
df_list <- split(iris, (iris$Species))

top.triangle <- 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.triangle <- 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)
}

#loop for generating species specific plots
for(i in 1:(length(df_list))){
  current.strain <- as.character(df_list[[i]]$Species[1])

  #declare file for saving png
  # png(paste0("~.test.triangle_", current.strain, ".png"),  width=650, height=500)
  plot.new()
  my.data = iris
  my.x.top = (iris %>% filter(Species == current.strain) )$nrm.Petal  
  my.y.top = (iris %>% filter(Species == current.strain) )$nrm.Sepal
  my.x.bottom = (iris %>% filter(Species == current.strain) )$nrm.Petal 
  my.y.bottom = (iris %>% filter(Species == current.strain) )$nrm.Sepal 

  op <- par(mar=c(3, 2, 2, 2) + 0.1, oma=c(2, 0, 0, 2))
  top.triangle(my.y.top, my.x.top, my.data)

  bottom.triangle(my.y.bottom+x.dist, my.x.bottom, my.data)

  par(op)
  RP[[i]] <- recordPlot()
  dev.off()
}

#for margins too large error
graphics.off()
par("mar") 
par(mar=c(.1,.1,.1,.1))

#draw and arrange the plots
ggdraw() + 
  draw_plot(RP[[1]], x=0, y=0)

#Add remaining plots
#draw_plot(RP[[2]], x=.25, y=.25)
#draw_plot(RP[[3]], x=.25, y=.25)

enter image description here

(this is built off the answer I posted from this question, R base plot, combine mirrored right triangles )

user1757654
  • 232
  • 2
  • 11
  • Make the plotting window in your RStudio application larger (ie, don't let it be just the tiny bottom right corner) – DanY May 15 '20 at 18:09
  • I've tried this and I can't plot a second plot even with the plotting window enlarged to most of the screen. – user1757654 May 15 '20 at 18:21
  • 1
    You need to use, e.g., `par(mfrow=c(3,3))` to make a 3x3 grid of plots. – DanY May 15 '20 at 20:12
  • What is the problem? Do you receive an error? What is wrong with plot posted here? Also, your code is not exactly reproducible as `top.triangle != top.triangle2` and `bottom.triangle != bottom.triangle2` and name changes is not enough since positional arguments are used. Test code in an empty R environment. And please specify all non-base packages with `library()` calls. – Parfait May 15 '20 at 20:16
  • Agree with @Parfait - if you want someone to work on your specific code, you need to edit it so we can run it. For example, your for-loop calls bottom.triangle() with a bunch of arguments whereas your code posted above defines the function bottom.traingle2() with no arguments. I also can't tell what x.dist should be nor can I figure out what 9 plots you are trying to make (your for-loop only loops over 3 things). Also, are there any libraries (other than dplyr) that are required to run the code? – DanY May 15 '20 at 20:17

1 Answers1

1

To use plot solution at specified link, you need to adjust to the iris data including your calculated columns, nrm.Sepal and nrm.Petal inside both functions. Then, instead of split, consider by to pass subsets into both functions for plotting. However, the plot will only generate 1 X 3. It is unclear how 3 X 3 is generated. Your posted link above actually duplicates

Data

iris$nrm.Sepal <- iris$Sepal.Width / iris$Sepal.Length
iris$nrm.Petal <- iris$Petal.Width / iris$Petal.Length

Functions

top.triangle <- function(my.data) {

  plot(nrm.Sepal ~ nrm.Petal, data= my.data, axes=FALSE, ylab="", xlab="", 
       main='', xlim=c(0, 1), ylim=c(0, 1), xaxt="n", yaxt="n", asp=1)
  mtext(my.data$Species[[1]], 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.triangle <- function(my.data) {
  x.dist <- .5
  my.data.2 <- transform(my.data, nrm.Sepal=nrm.Sepal + x.dist)

  points(nrm.Petal ~ nrm.Sepal, data=my.data.2, col="red", 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] + 3)
  x.at <- axisTicks(par()$usr[1:2], 0) + x.dist
  axis(side=1, las=1, pos=0, at=x.at, 
       labels=FALSE, xpd=TRUE)
  mtext(seq(0, 1, 0.2), 1, 0, at=x.at, cex=0.7)
  axis(4, las=1, pos=1 + x.dist)
  lines(0:1 + x.dist, 0:1, xpd=TRUE)
}

Plot

par(mar=c(1, 4, 8, 6), oma=c(2, 0, 0, 2), mfrow=c(2,3))

by(iris, iris$Species, function(sub){
  top.triangle(sub)
  bottom.triangle(sub)
})

Plot Output

Parfait
  • 104,375
  • 17
  • 94
  • 125
  • sorry for the typos, I edited the post. The iris data set was just meant as a workable example. I just threw that figure together as example. My data set for this figure has more categories. I'm not that familiar with base plotting, it helps to see more solutions. I'll read up more about 'by'. – user1757654 May 15 '20 at 23:22
  • Did you test your code? As I commented above you cannot simply rename functions as you pass in arguments that your functions do not define. Please `dput` a sample of your actual data for [reproducible example](https://stackoverflow.com/q/5963269/1422451). But as this solution shows tailor plot functions to data. If you have 9 groups, `by` will capture them. – Parfait May 15 '20 at 23:50