The problem is that I managed to graph this:
by writing this:
par(mar=c(0,4,2,1)+.1)
shap <- shapiro.test(as.numeric(residuals.arima))$p.value
qqnorm(residuals.arima, main=c("Normal Q-Q Plot", paste("Shapiro p=", prettyNum(shap, digits = 2))))
qqline(residuals.arima)
op <- par(fig=c(.02,.5,.5,.98), new=TRUE)
hist(residuals.arima, breaks=22, probability=T,
col="grey", xlab="", ylab="", main="", axes=F)
lines(a,dnorm(a,mean(residuals.arima), sd(residuals.arima)), lty=1, col="darkblue", lwd=2)
box()
par(op)
Now, this is exactly the way I'd like the two plots to be visualized together. I do not want to split them up.
However I'd like to put everything in the right panel (2) of a structure like the following, so that I can add another plot on panel (1) without everything messing up:
layout(matrix(c(1,2), nr=1, byrow = TRUE))
How can I do this?
If I understand you correctly you want to simply do this:
par(mfrow=c(1,2))
qqplot(...)
qqline(...)
hist(...)
lines(...)
Alternative interpretation of what you are after is to put everything you have on that second side and leave the first side blank (to be used for something else). If that is the case you can use screen:
figs <- rbind(c(0, 0.5, 0, 1), # Screen1
c(0.5, 1, 0, 1), # Screen2
)
colnames(figs) <- c("W", "E", "S", "N")
rownames(figs) <- c("Screen1", "Screen2")
screenIDs <- split.screen(figs)
names(screenIDs) <- rownames(figs)
screen(screenIDs["Screen1"])
# Everything that should go on the left side goes here
screen(screenIDs["Screen2"])
# The current plots you have go here
Related
Suppose data
set.seed(42)
a <- rnorm(100)
b <- rnorm(100)+1
which I would like to plot side-by-side using multhist().
multhist(list(a,b), yaxs="i")
Now I would like to draw a box around them
box(which = "plot", lty = "solid")
which gives me
with some space between the bottom line of the box and the bars.
Had I used hist() to plot only one graph, the ouput would have been without gap between box and bars:
Is there a different trick to get such an output in multhist()?
I think setting ylim mentioned by #KamranEsmaeili is a standard solution. Here I provided a tricky way that doesn't require manually setting the upper limit 40.
multhist() is based on the built-in barplot() and it always sets the lower limit of y-coordinate of the plotting region less than 0. You can use par("usr")[3] to check this fact. I just came up with a tricky method that adjusts the box type to "7" to suppress the bottom line and add a new bottom line at 0 by abline(h = 0).
library(plotrix)
set.seed(42)
a <- rnorm(100)
b <- rnorm(100) + 1
multhist(list(a,b))
#---------------------------------
box(bty = "7") # bty is one of "o"(default), "l", "7", "c", "u", and "]".
abline(h = 0)
Edit
If you don't like the right line extending beyond the x axis, then you can replace box() with rect() so that you can specify positions of four sides by yourself. Remember to add xpd = TRUE, or the line width will look thinner than y-axis.
multhist(list(a,b))
x <- par("usr")
rect(x[1], 0, x[2], x[4], xpd = TRUE)
Just add "space=c(0,0)" and "ylim" and you good to go:
multhist(list(a,b), yaxs="i", space=c(0,0), ylim=c(0,40))
I need to put two plots side by side. As such, not a hard exercise, except that:
I want and need to use basic graphics
the plots should be placed seamlessly next to each other.
Here is an example how I solve it
x2 <- seq(1.9, 7.3, length.out=10)
x1 <- seq(0.2, 5.8, length.out=10)
y1 <- rnorm(10)
par(mfrow=c(1,2))
par(mar=c(5,4,4,0))
plot(x1, y1, type="l", bty="n", xlim=range(x1), ylim=c(-2, 2))
par(mar=c(5,0,4,2))
plot(x2, y1, type="l", bty="n", xlim=rev(range(x2)), ylim=c(-2, 2), yaxt="n")
Here is the problem: I would like the two lines to touch or almost touch. If the axes are separated, that is OK; but the distance between these two plots should be minimal. Optimally, I will want to have fat red vertical line showing where the two parts of the plot meet.
None of the answers I have found so far allow me to do that.
Context: I am plotting a genomic rearrangement in which two distant parts of some chromosomes were fused together, one of them reversed (hence the different scaling).
Add xaxs = "i" into the fist par(), i.e.
par(mfrow = c(1, 2), xaxs = "i")
and run the entire code again.
xaxs indicates the style of axis interval calculation to be used for the x-axis. The default is "r"(regular) which extends the data range by 4 percent at each end. Revising it to "i" will make the x-axis fit within the original data range.
While #DarrenTsai's answer is absolutely correct, you'll find that the x-axis scales take up different values per pixel when they have different mar parameters. I suggest you consider plotting them together and then adding a custom axis.
x2 <- seq(1.9, 7.3, length.out=10)
x1 <- seq(0.2, 5.8, length.out=10)
y1 <- rnorm(10)
ValueTable <- data.frame(Foward = c(x1,max(x1) + (x2-min(x2))), Join = c(x1,rev(x2)))
plot(ValueTable$Foward,c(y1,rev(y1)),type = "l",xaxt="n",xlab = "",ylab = "Value")
axis(1, ValueTable$Foward[seq(1,nrow(ValueTable),by = 2)], labels=formatC(ValueTable$Join[seq(1,nrow(ValueTable),by = 2)],format = "f", digits = 2))
abline(v=max(x1))
I'm using Markdown to write my thesis dissertation.
Basically I split the screen to arrange two plot in one, but I would like to reduce the size of the entire plot. So i did this:
figs <- rbind(c(0, 0.5, 0, 0.8), # Screen1 reduced from 1 to 0.8
c(0.5, 1, 0, 0.8)) # Screen2 reduced from 1 to 0.8
colnames(figs) <- c("W", "E", "S", "N")
rownames(figs) <- c("Screen1", "Screen2")
screenIDs <- split.screen(figs)
names(screenIDs) <- rownames(figs)
# Left Side plot:
screen(screenIDs["Screen1"])
par(mar=c(4,4,2,1)+.1)
qqnorm(...)
qqline(...)
op <- par(fig=c(0.01,.3,.35,.78), new=TRUE)
hist(...)
lines(a,dnorm(a,mean(residuals.arima), sd(residuals.arima)), lty=1, col="darkblue", lwd=2)
box()
par(op)
#Right side plot:
screen(screenIDs["Screen2"])
par(mar=c(4,4,2,1)+.1)
plot(...)
lines(...)
Unfortunately what I get is the following (I've highlighted the extra space in red):
so it seems I just reduce the plot size but not the total plotting output size.
How can I deal with it? I don't want to fill the gap with my picture since it would be too big.
I want to plot single bar in a graph so it would look like picture below
I created test data and calculate its mean.
value <- c(99,44,100,120,88)
value_mean <- mean(value)
And plot them using below code
barplot(value_mean, horiz=T, width=30, cex.names=0.5 ,ylim=c(0,200), col="red")
Buth the output is not even close.
I've also looked at this links
Single bar barchart in ggplot2, R
R Barplot with one bar - how to plot correctly
So my output should be something like the first picture. I was thinking that could solve ggplot.
If everything else fails, you can draw a rectangle like this:
par(mar = c(12, 2, 12, 2))
plot(0, type="n", ylim=c(-1, 1), xlim=c(0, 200), axes = F, bty = "n",ylab="", xlab="label")
rect(0, -.7, value_mean, .7, col="red", border=NA)
text(value_mean, 0, pos=4, label=value_mean)
axis(1, at=seq(0, 200, by=40))
If I have several plots in a single panel, I would like to be able to put text annotations that go across more than one plot area or that go in between plot areas. I'm sure there must be a way to do this, but I need some help figuring out how.
Here's some fake data to create four plots on one panel:
x1 = rnorm(100)
x2 = rnorm(100)
x3 = rnorm(100)
x4 = rnorm(100)
par(mfrow=c(2,2))
hist(x1, xlab="", main="Group A")
hist(x2, xlab="", main="Group B")
hist(x3, xlab="", main="")
hist(x4, xlab="", main="")
This creates the multi-plot panel below, except that I've also added text in red. I added the red text by annotating the PDF file after I created the graph panel in R and then saved it as a PDF. What I'd like to learn is how to annotate the graph panel programmatically within R, rather than having to save it and annotate the saved file.
Normally, I would just add an annotation using text() or mtext(). But that only works if you're annotating a single graph. Is there a way to add annotations relative to the coordinates of the entire panel of 4 graphs? I'm looking for a solution in base graphics right now, but if anyone knows how to do something similar in ggplot2 or lattice, I'd be interested in seeing that as well.
If you truly want finer control over these kinds of layout issues, you can use the aptly named layout.
m <- matrix(c(1,2,3,3,4,5,6,6),ncol = 2,byrow = TRUE)
layout(m,widths = c(0.5,0.5),heights = c(0.45,0.05,0.45,0.05))
par(mar = c(2,4,4,2) + 0.1)
hist(x1, xlab="", main="Group A")
hist(x2, xlab="", main="Group B")
par(mar = c(0,0,0,0))
plot(1,1,type = "n",frame.plot = FALSE,axes = FALSE)
u <- par("usr")
text(1,u[4],labels = "Here",col = "red",pos = 1)
par(mar = c(2,4,2,2) + 0.1)
hist(x3, xlab="", main="")
hist(x4, xlab="", main="")
par(mar = c(0,0,0,0))
plot(1,1,type = "n",frame.plot = FALSE,axes = FALSE)
u <- par("usr")
text(1,u[4],labels = "Here",col = "red",pos = 1)
You want to use mtext with outer=TRUE. For instance, mtext('Results2', side=1, line=-2, outer=TRUE) and mtext('Results1', side=3, line=-20, outer=TRUE).
For this example the layout function is simplest as has been already shown, but for more general cases you should also learn the grconvertX and grconvertY functions (along with setting clipping using par(xpd=. The convert functions can give you the coordinates in the current user coordinates for different coordinate systems, so for example you could center something on the page by converting 0.5 from the normalized device coordinates.
Here is an example using Greg Snow's approach:
par(mfrow=c(2, 2))
replicate(4, plot(matrix(runif(20), nrow=10)))
text(grconvertX(.5, "ndc", "user"), grconvertY(.25, "ndc", "user"), "TEST", cex=3, col="red", xpd=NA)
text(grconvertX(.5, "ndc", "user"), grconvertY(.75, "ndc", "user"), "TEST", cex=3, col="red", xpd=NA)