Hi everybody I have 3 plots with density bars on either axis which I have done this way (here is a simpler form presented with only 3 ordinary plots but the other parts are necessary as required for a more complicated function which I have left off here just for the ease of viewing)
scatterBar.Norm <- function(x,y) {
zones <- matrix(c(2,0,1,3), ncol=2, byrow=TRUE)
layout(zones, widths=c(5/7,2/7), heights=c(2/7,5/7))
title("My Title", outer=TRUE);
par(mar=c(3,3,1,1),mgp=c(2,1,0))
plot(1:10, xlab="Magnification", ylab="residue", col=2)
par(mar=c(0,3,1,1))
plot(1:10, xlab="Magnification", ylab="residue",col=3)
par(mar=c(3,0,1,1))
plot(1:10, xlab="Magnification", ylab="residue", col=4)}
scatterBar.Norm(2,3)
The problem :
Firstly the The plot title the "My Title" part is going out of the canvas , how to fix it ?
Thanks for the much needed help in advance.
You've instructed R to plot the title in the outer margin, but (at least in your example) you haven't set up that margin. The following should work:
scatterBar.Norm <- function(x, y) {
zones <- matrix(c(2, 0, 1, 3), ncol=2, byrow=TRUE)
layout(zones, widths=c(5, 2), heights=c(2, 5))
par(mar=c(3, 3, 1, 1), mgp=c(2, 1, 0), oma=c(0, 0, 3, 0))
plot(1:10, xlab="Magnification", ylab="residue", col=2)
par(mar=c(0, 3, 1, 1))
plot(1:10, xlab="Magnification", ylab="residue", col=3)
par(mar=c(3, 0, 1, 1))
plot(1:10, xlab="Magnification", ylab="residue", col=4)
title("My Title", outer=TRUE)
}
plot.new()
scatterBar.Norm(2, 3)
Related
I have generated a bar plot/histogram for my data which shows the number of transactions for pack size. However, labels on x axis for the bars are out of the margin. The plot is presented below.
I have tried to fix this by setting the outer margin to par(oma=c(3,3,0,0)). Here is my new plot.
Although, the labels are inside the graph margin, but the x-axis title is still overlapped with the labels. How should I adjust the axis title so it is not overlapped with the labels?
Any suggestions would be very much appreciated!
Use axis and mtext.
par(mar=c(11, 6, 4, 2))
b <- barplot(data$v, ylim=c(0, 2e4), yaxt='n',
main='Number of Transactions by Life Stage Histogram'
)
mtext(data$l, 1, .5, at=b, las=2, cex=.7)
axis(2, labels=F)
mtext(axTicks(2), 2, .75, at=axTicks(2), las=2)
mtext('Life Stage', 1, 9)
mtext('Freequency', 2, 4)
Or maybe that might be better:
par(mar=c(3, 5, 4, 3))
b <- barplot(data$v, ylim=c(0, 15e3), ylab='Frequency', yaxt='n',
main='Number of Transactions by Life Stage'
)
axis(2, labels=F)
mtext(axTicks(2), 2, .75, at=axTicks(2), las=2, cex=.8)
y <- (data$v) * c(1, 1, 1, 0, 0, 0, 0) + 500
text(b, y, data$l, srt=90, adj=0, cex=.7)
mtext('Life Stage', 1, 1)
Data:
data <- structure(list(l = c("MIDAGE SINGLES/COUPLES", "NEW FAMILIES",
"OLDER FAMILIES", "OLDER SINGLES/COUPLES", "RETIREES", "YOUNG FAMILIES",
"YOUNG SINGLES/COUPLES"), v = c(7500, 2500, 1000, 15000, 15100,
10000, 15000)), class = "data.frame", row.names = c(NA, -7L))
Taking jay.sf example as one for any plot we could add:
title(xlab = "My Label", line = 10)
Where line is adaptable: 10 or 9 or 8 etc...
plot.new()
par(mar=c(11, 6, 4, 2))
b <- barplot(data$v, ylim=c(0, 2e4), yaxt='n',
main='Number of Transactions by Life Stage Histogram'
)
mtext(data$l, 1, .5, at=b, las=2, cex=.7)
axis(2, labels=F)
mtext(axTicks(2), 2, .75, at=axTicks(2), las=2)
mtext('Life Stage', 1, 9)
mtext('Freequency', 2, 4)
title(xlab = "My Label", line = 10)
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)
(this is built off the answer I posted from this question, R base plot, combine mirrored right triangles )
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)
})
The headings of the "text" are strangely located at different y-coordinates, although they are defined exactly the same, also the pars are the same.
Besides, I want somewhat narrower spacing in the legend, cex won't help anything.
I could add some space in -style (see MARK in code) which looks somewhat better but doesn't fix the spacing:
Does anybody know how to deal with that (w/o extra packages)?
The output of the legend should look something like this:
Code producing plot
# pdf("test.pdf", width=8, height=4)
layout(matrix(c(1, 3, 2, 3), ncol=2), heights=c(4, 1.5))
par(mai=c(0, .5, .5, .25))
plot(1:10)
mtext(bquote(bold("Linear points")), 3, 0, cex=.9, adj=0, padj=-.3)
par(mai=c(0, .5, .5, .25))
curve(x^2)
mtext(bquote(bold("A curve")), 3, 0, cex=.9, adj=0, padj=-.3)
par(mai=c(0, 0, .375, 0))
plot.new()
legend("center", legend=c("The quick", "brown fox", "jumps over",
"the lazy dogs",
# expression(paste(" ", alpha~"=5%")), # MARK
expression(alpha~"=5%"),
"DF=Dgs. of freedom"),
lty=c(rep(1, 4), rep(NA, 2)), bg="white", col=1:4,
xpd=TRUE, pt.cex=1.1, horiz=TRUE, cex=.7)
# dev.off()
So i have this numeric variables which reflect percentages
data1.pct<-19
data2.pct<-5
data3.pct<-76
class1.pct<-35
class2.pct<-18
class3.pct<-47
Now i am using this code to generate barplot
CairoPDF(paste('data1/', data, '_plot1.pdf', sep=''), family='sans', pointsize=9, width=6, height=3.25)
par(mar=(c(4, 4, 1, 13) + 0.1), mgp=c(3, 2, 0), xpd=TRUE)
barplot(cbind(
c(data1.pct, data2.pct, data3.pct),
c(class1.pct, class2.pct, class3.pct)), col=c("firebrick3", "dodgerblue3", "mistyrose1"), ylim=c(0,100), space=c(0,1)
)
legend("topright", inset=c(-0.55, 0), legend=c("not attend", "refused", "attend"), col=c("mistyrose1", "dodgerblue3", "firebrick3"), lty=1, lwd=2, bty='n')
dev.off()
and the result is
I would like to add corresponding percentages inside barplot, that is numbers/percentages in my variables. So My output should be:
I would like to use barplot funcion to do this and NOT ggplot2
I have tried adding percentages with
text(mydata, 0, round(data1.pct), 1),cex=1,pos=3) but this is not right.
To get the y-values for the text, you can use cumsum along with tail and head to get the midpoints of each bar section.
par(mar=(c(4, 4, 1, 13) + 0.1), mgp=c(3, 2, 0), xpd=TRUE)
## Make the matrix for barplot
mat <- cbind(c(data1.pct, data2.pct, data3.pct), c(class1.pct, class2.pct, class3.pct))
## Get the y-values for text
ys <- apply(mat, 2, function(x) c(x[1]/2, head(cumsum(x),-1) + tail(x,-1)/2))
## Make barplot, store x data
xs <- barplot(mat, col=c("firebrick3", "dodgerblue3", "mistyrose1"), ylim=c(0,100), space=c(0,1))
## Add text
text(rep(xs, each=nrow(ys)), c(ys), labels=c(mat))
legend("topright", inset=c(-0.55, 0), legend=c("not attend", "refused", "attend"), col=c("mistyrose1", "dodgerblue3", "firebrick3"), lty=1, lwd=2, bty='n')
In order to generate a layout with multiple plots, I have the following code with some dummy plots:
jpeg("/path/to/file",height=10000,width=5000)
plot.new()
par(mar=c(2,2,1,1), oma=c(2,4,0,0), xpd=NA)
for (i in 1:10) {
par(mar=c(2,2,1,1),fig=c(0, 0.5, (10-i)/10, (11-i)/10), new=T)
matplot(rnorm(20)*sample(100,1),
col="blue",axes=F,type="l",lwd=10, xlab="",ylab="")
par(mar=c(2,2,1,1),fig=c(0.5, 1, (10-i)/10, (11-i)/10), new=T)
matplot(rnorm(20)*sample(100,1),
col="red",axes=F,type="l",lwd=10, xlab="",ylab="")
}
dev.off()
I want to add a vertical line/axis on the far LHS and the far RHS that span all 10 plots in a column. Since I will use this line as an axis, I need to be able to add ticks and labels.
You could draw axis by ?axis or ?Axis. To span your axis on multiple plots you have to reset the usr coordinates.
Please find a base graphics solution below:
## store number of rows
nRow <- 10
## your example code
## (only the number "10" is replaced by nRow and oma is adapted)
plot.new()
par(mar=c(2, 2, 1, 1), oma=c(2, 4, 0, 4), xpd=NA)
for (i in 1:nRow) {
par(mar=c(2, 2, 1, 1), fig=c(0, 0.5, (nRow-i)/nRow, ((nRow+1)-i)/nRow), new=TRUE)
matplot(rnorm(20)*sample(100, 1),
col="blue", axes=F, type="l", lwd=10, xlab="", ylab="")
par(mar=c(2, 2, 1, 1), fig=c(0.5, 1, (nRow-i)/nRow, ((nRow+1)-i)/nRow), new=TRUE)
matplot(rnorm(20)*sample(100, 1),
col="red", axes=F, type="l", lwd=10, xlab="", ylab="")
}
## define new user coordinates
usr <- c(0, 1, 0, 1) ## x1, x2, y1, y2
## calculate tick positons
## in general: (usr[3]+(diff(usr[3:4])/(nRow-1))*0:(nRow-1))
## but our usecase is much easier:
ticksAt <- 1/(nRow-1)*0:(nRow-1)
## choose left column and reset user plotting area (usr)
par(mar=c(2, 2, 1, 1), fig=c(0, 0.5, 0, 1), usr=usr, new=TRUE)
## draw axis; see ?Axis for details
Axis(side=2, at=ticksAt, labels=as.character(1:(nRow)), line=0.5)
## choose right column and reset user plotting area (usr, not needed because already done)
par(mar=c(2, 2, 1, 1), fig=c(0.5, 1, 0, 1), usr=usr, new=TRUE)
## draw axis; see ?Axis for details
Axis(side=4, at=ticksAt, labels=as.character((nRow+1):(2*nRow)), line=0.5)
You could make one overall plot of the entire device, add the axes there, then use the subplot function (TeachingDemos package) to do the plots within the large plot.