I have succeeded in creating and aligning three scatter-plots in R, using the following code:
par(mfrow = c(3,1))
plot(CGP.GOSL ~ FPT.MAF.GOSL, data = all.locs, main = "A. Place I")
abline(h=c(0.5))
abline(v=c(0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5), lty=2)
plot(CGP.IRE ~ FPT.MAF.IRE, data = all.locs, main = "B. Place II")
abline(h=c(0.5))
abline(v=c(0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5), lty=2)
plot(CGP.BAR ~ FPT.MAF.BAR, data = all.locs, main = "C. Place III")
abline(h=c(0.5))
abline(v=c(0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5), lty=2)
What I would like to do now is save space by having a single Axis label for the x and y axis. I have tried experimenting with the par() function, inserting x and ylab functions, but it seems that as these are not graphical parameters is will not accept them. I suspect the problem lies in where I place this information in the code, as using the xlab and ylab seems to make sense, and I can write x and ylab = "" in the individual plot codes.
I am also struggling to change the position of the main titles so that the appear on the left, to remove the values from the x-axis so that they only show at the bottom of the whole figure, and to arrange the figure so that there is less space.
This figure shows the current layout and the layout I want to achieve:
I am sorry to post so many questions at once. I am very new to R and programming am still finding the helpfiles a bit daunting, although I am getting there. Some suggestions on functions, where to put them and how to use them to achieve some of these aims would be great.
The documentation can be a bit challenging at times. Here's a skeleton for what I think you're looking for:
# 3 rows
par(mfrow=c(3,1))
# tighter margins
par(mar = c(0, 0, 0, 0), oma = c(4, 4, 0.5, 0.5))
# need some data
data(cars)
# 3 plots, no axis junk
plot(cars, ann=FALSE)
plot(cars, ann=FALSE)
plot(cars, ann=FALSE)
# outer labels
mtext("x axis", side = 1, outer = TRUE, cex = 0.7, line = 2.2)
mtext("y axis", side = 2, outer = TRUE, cex = 0.7, line = 2.2)
This answer is based on hrbrmstr's answer, but the result is closer to the requested layout:
# 3 rows
par(mfrow=c(3,1))
# Adjust margins. Each vector element refers to one side of the plot;
# the order is c(bottom, left, top, right). (See ?par)
par(mar = c(2.5, 4.1, 1, 2.1), oma = c(3, 3, 2, 0))
# need some data
data(cars)
# 3 plots. On the first two: Suppress axis labels (ann = FALSE) and
# the x axis (xaxt = "n"), then add the ticks using axis() and the
# title using mtext(). On the last one, do not suppress x axis.
# Note that repeating arguments could be set globally using par().
plot(cars, ann = FALSE, xaxt = "n")
axis(side = 1, labels = FALSE)
mtext(text = "A. Place I", side = 3, at = par("usr")[1], line = 1)
plot(cars, ann=FALSE, xaxt = "n")
axis(side = 1, labels = FALSE)
mtext(text = "B. Place II", side = 3, at = par("usr")[1], line = 1)
plot(cars, ann=FALSE)
mtext(text = "C. Place III", side = 3, at = par("usr")[1], line = 1)
# outer labels
mtext("X Axis label", side = 1, outer = TRUE)
mtext("Y Axis label", side = 2, outer = TRUE)
Related
When creating a sunflower plot for logistic regression, the x-axis starts at 2. Can I change this behaviour to make the x-axis start at 0? I've already tried to manually change this by changing the x-axis, but that didn't make x=0 visible (see #c1).
The Sunflower Plot Image as it currently is, starting at x=2;
# EE contains the Likert Scale values
EE.min <- min(EE)
EE.max <- max(EE)
EE.x <- seq(EE.min, EE.max, length = 500)
New.EE <- data.frame(EE = EE.x)
# Creating prediction
EE.p <- predict(logit, New.EE, type = "response")
sunflowerplot(EE, cb, main = "Effort Expectancy",
xlab= "EE (5-point Likert-Scale)", ylab="Likelihood", yaxt="n", xaxt="n")
# c1:
axis(1, at = seq(0,5,0.5), labels = c(0, 0.5, 1, 1.5, 2, 2.5 , 3, 3.5, 4, 4.5, 5), las=1)
axis(2, at = seq(0,1,0.2), labels = c("No = 0", 0.2, 0.4, 0.6, 0.8, "Yes = 1"), las = 2)
abline(h = seq(0,1,0.2), lty = 2)
lines(EE.x, EE.p)
sunflowerplot has an argument xlim for the limits of the x axis.
Compare
sunflowerplot(iris$Sepal.Length, iris$Sepal.Width)
to
sunflowerplot(iris$Sepal.Length, iris$Sepal.Width, xlim = c(0, 20))
I've found an issue when setting pos = n when I use the axes command for creating charts in R. When the y-axis range is -6 to -1, it all works perfectly, but when my range is for example -5 to -2 the axes won't meet at the specified position; the y-axis omits the -5 label and tick mark.
The code for one of my charts is as follows:
x <- c(3179047.6, 1956470.4, 609295.9, 136037.6)
y <- c(-4.758698, -4.227640, -4.019197, -2.653719)
model_fit <- lm(y~x)
par(mar=c(2.1, 2.1, 2.5, 1.1)) # I want to reduce the white space around the margins
plot(x, y, axes = FALSE, xlab = NULL, ylab = NULL, # I set the axes manually afterwards
ylim = c(c(min(0, y)), ceiling(max(y))),
xlim = c(0, 1000000*ceiling(max(x)/1000000)))
lines(x4, predict(model_fit), lty = 2, col = "red")
mtext(side = 1, line = 1.1, expression(paste(epsilon^"2")), cex = 0.7) # Greek symbol squared, title repositioned, font size lowered.
mtext(side = 2, line = 0, "Y-axis Title\n(units)", cex = 0.7) # font size lowered
mtext(side = 3, line = -0.5, "Main\nTitle",
cex = 0.8, font = 2)
axis(1, seq(0, 1000000*ceiling(max(x)/1000000), 1000000),
labels = seq(0, 1000000*ceiling(max(x)/1000000), 1000000),tck = -0.02, cex.axis = 0.6, padj = -3, pos = floor(min(y4)))
axis(2, seq(floor(min(y)), ceiling(max(y)), 1),
labels = seq(floor(min(y)), ceiling(max(y)), 1), tck = -0.02, cex.axis = 0.6, padj = 2, pos = 0)
par(mar=c(5.1, 4.1, 4.1, 2.1)) # Resetting the default margin sizes
For the axis() commands I've first set the range by seq(0, 1000000*ceiling(max(x)/1000000), 1000000), and then I repeated the command by setting labels = seq(0, 1000000*ceiling(max(x)/1000000), 1000000) to manually force the code to return the tick marks and labels at the correct position.
Then for the x-axis (axis 1), I set the position where it meets the y-axis (axis 2) at the minimum value of the y axis range by setting pos = floor(min(y4). The issue is for the chart produced by the above code, instead of having the y-axis extend down to meet the x-axis, there's a space and no tick or label for the -5 point.
This only happens when the range is between -2 and -5, for my chart where the range is -1 to -6, the two axes meet.
Is there some underlying code in the axis command I need to override?
I would like data labels to appear at the end of each bar, with one space between the label and the end of the bar. I would like the labels to be expressed as percents. Please note, the graph was constructed using raw numbers, not percentage values. I would like the solution to this problem to be in base R. Answers to similar prior questions have not worked for me.
table(cont$cont9) # 1=0, 2=0,3=2, 4=2, 5=21
#1=0%, 2=0%,3=8%, 4=8%, 5=84%
par(mar=c(0, 5, 0, 2.1))
H <- c(0, 0, 2, 2, 21) # Create the data for the chart, cont3.#
M <- c("Very Low", "Low", "Medium", "High", "Very High")
barplot(H, col =c("slategray1", "slategray1","slategray1",
"slategray1", "steelblue3"),
horiz = TRUE,
family="Arial", border = NA, names.arg = M,
xlim = range(0,100), ylim = range(0, 0.08),
axes = FALSE, width = 0.01, las=1, xaxt='n')
I would like percentage data labels at the end of each bar. With the solution in base R.
To do what the question asks for, keep the return value of barplot and use it as the y coordinates of the labels. The return value is:
A numeric vector (or matrix, when beside = TRUE), say mp, giving the
coordinates of all the bar midpoints drawn, useful for adding to the
graph.
The x coordinates are the plotted values, with the position adjusted, pos = 4.
In the code that follows, I start by also keeping the return value of the call to par. This is a general purpose good habit. When done plotting, reset the defaults as they were.
op <- par(mar=c(0, 5, 0, 2.1))
bp <- barplot(H, col =c("slategray1", "slategray1","slategray1",
"slategray1", "steelblue3"),
horiz = TRUE,
family = "Arial", border = NA, names.arg = M,
xlim = range(0,100), ylim = range(0, 0.08),
axes = FALSE, width = 0.01, las=1, xaxt='n')
text(H, bp, labels = H/sum(H), pos = 4)
par(op)
Note:
Though I have not change it, I find
xlim = c(0, 30), ylim = c(0, 0.08),
more natural.
It uses c, not range.
The xlim values agree with range(H).
ENV
R 3.3.1
mini data
rdn<-c(0.8,1.8,2.8)
tdn<-c(1,2,3,4,5,6,7,8,9)
idn<-matrix(c(0.3, 0.3, 0.3, 0.2, 0.2, 0.4, 0.1, 0.1, 0.5, 0, 0.2, 0.5, 0, 0.3, 0.6, 0, 0.4, 0.6, 0, 0.4, 0.6, 0, 0.5, 0.7, 0, 0.5, 0.7), nrow=9, ncol=3, byrow=T)
What I have now:
code
filled.contour(tdn, rdn, idn,
color.palette=colorRampPalette(c("blue","yellow","red")),
plot.title=title(main="Detail", sub="detail",
xlab="t", ylab="lambda"),
plot.axes = { axis(side = 1, at = tdn, labels = tdn)
axis(side = 2, at = rdn, labels = rdn) },
key.title=title(main="ratio"),
key.axes = axis(4, seq(0, 1, by = 0.1)))
Current Result
Problem
The color range is not what I want. There are borders among colors so colors do not change smoothly from deep blue to deep red.
Expected
Question
how to make colors change smoothly like my Expeced figure when plotting in R? How do I remove problems above? And rainbow not works for me either. Thanks.
EDIT
Follow Haboryme's solution
The foreground not disappear.
Close to #setempler answer but you might find it a bit closer to your expected output:
par(fg = NA,col="black")
filled.contour(x=tdn,
y=rdn,
z=idn,
color.palette=colorRampPalette(c("blue","yellow","red")),
plot.title=title(main="Detail", sub="detail",
xlab="t", ylab="lambda"),
nlevels=200,
plot.axes = { axis(side = 1, at = tdn, labels = tdn)
axis(side = 2, at = rdn, labels = rdn) },
key.title=title(main="ratio"),
key.axes = axis(4, seq(0, 1, by = 0.1)))
Unfortunately, filled.contour ...
fixes the number of levels/colours between the plot and key, so experimenting with the nlevels argument (and col instead color.palette) results in a weird output (smoother image, but unreadable key).
In addition, the contour lines cannot be modified. Thus, an increase to 200 levels (from initially 14 in your example) is still 'readable', but higher values generate unwanted side-effects.
Example:
n <- 200
filled.contour(tdn, rdn, idn,
col=colorRampPalette(c("blue","yellow","red"))(n),
levels = seq(0,1,length.out = n),
plot.title=title(main="Detail", sub="detail",
xlab="t", ylab="lambda"),
plot.axes = { axis(side = 1, at = tdn, labels = tdn)
axis(side = 2, at = rdn, labels = rdn) },
key.title=title(main="ratio"),
key.axes = axis(4, seq(0, 1, by = 0.1)))
Output:
Maybe experimenting with lattice::levelplot solves the problem. At least for the legend color key, a higher number of levels does not disturb. But the image is not 'smoothed'.
Example:
library(lattice)
levelplot(idn, row.values = tdn, column.values = rdn, cuts = n, col.regions = colorRampPalette(c("blue","yellow","red"))(n))
Output:
I have two plots that I would like to overlay in a particular way. Instead of side by side like when using par(), I would like one to sit inside the other, but be about a quarter the size.
More details: one of my plots is a map, another is a scatterplot with colored quadrants. The colored quadrants represent the colors plotted onto the map, so I would like to inset it nicely in the same plot as the map so that it serves as a legend.
Thanks in advance
Here's an example, although the links in comments point to similar approaches.
Grab a shapefile:
download.file(file.path('http://www.naturalearthdata.com/http/',
'www.naturalearthdata.com/download/50m',
'cultural/ne_50m_admin_1_states_provinces_lakes.zip'),
{f <- tempfile()})
unzip(f, exdir=tempdir())
Plotting:
library(rgdal)
shp <- readOGR(tempdir(), 'ne_50m_admin_1_states_provinces_lakes')
plot(subset(shp, admin=='Australia'),
col=sample(c('#7fc97f', '#beaed4', '#fdc086', '#ffff99'),
9, repl=TRUE))
opar <- par(plt=c(0.75, 0.95, 0.75, 0.95), new=TRUE)
plot.new()
plot.window(xlim=c(0, 1), ylim=c(0, 1), xaxs='i', yaxs='i')
rect(0, 0, 0.5, 0.5, border=NA, col='#7fc97f')
rect(0.5, 0, 1, 0.5, border=NA, col='#beaed4')
rect(0, 0.5, 0.5, 1, border=NA, col='#fdc086')
rect(0.5, 0.5, 1, 1, border=NA, col='#ffff99')
points(runif(100), runif(100), pch=20, cex=0.8)
box(lwd=2)
par(opar)
See plt under ?par for clarification.
This is how I did it in the past
grid.newpage()
vp <- viewport(width = 1, height = 1)
submain <- viewport(width = 0.9, height = 0.9, x = 0.5, y = 1,just=c("center","top"))
print(p, vp = submain)
subvp2 <- viewport(width = 0.2, height = 0.2, x = 0.39, y = 0.35,just=c("right","top"))
print(hi, vp = subvp2)
subvp1 <- viewport(width = 0.28, height = 0.28, x = 0.0, y = 0.1,just=c("left","bottom"))
print(ak, vp = subvp1)
in my case p, ak and hi were gg objects (maps created with ggplot) and I was inserting a small version of each near the main use map (p) - as it is typically done