I have the following function
C=15
S=seq(0,12,.1)
pA=1
pS=0.5
A <- function(S) (C/pA)-(pA/pS)*S
plot (S, A(S), type="l", col="red", ylim=c(0,15), xlim=c(0,15), xlab="S", ylab="A")
text(8, 11.5, "Function", col = "red", cex=.9)
text(11, 10.2, expression(A==frac(C,p[S])-frac(p[A],p[S])%.%S), cex=.9, col = "red")
grid()
How can I scale the axis so that I can "zoom out" a bit. I am looking for a function similar to ylim but where I could say: ylim=c(0,15, by=1).
Update
It seems your "zoom out" is meant for the grid lines, not for the axis or anything. I'll keep the previous answer below, but this should address it, I think.
# no change yet
plot (S, A(S), type="l", col="red", ylim=c(0,15), xlim=c(0,15), xlab="S", ylab="A")
text(8, 11.5, "Function", col = "red", cex=.9)
text(11, 10.2, expression(A==frac(C,p[S])-frac(p[A],p[S])%.%S), cex=.9, col = "red")
# no call to grid, since we want to control it a little more precisely
abline(h = seq(0, 15), col = "lightgray", lty = "dotted", lwd = par("lwd"))
abline(v = seq(0, 15, by = 5), col = "lightgray", lty = "dotted", lwd = par("lwd"))
You can do just abline(h=seq(...)) and not set col=, lty=, or lwd=, but realize that abline's default values are different from grid's defaults. I used those values to mimic grid's look and feel.
Old answer
I think you mean to change the y axis labels, not the y axis limits (which is all that ylim= can effect).
Using base R graphics:
plot (S, A(S), type="l", col="red", ylim=c(0,15), xlim=c(0,15), xlab="S", ylab="A",
yaxt = "n") # this is new
text(8, 11.5, "Function", col = "red", cex=.9)
text(11, 10.2, expression(A==frac(C,p[S])-frac(p[A],p[S])%.%S), cex=.9, col = "red")
grid()
axis(2, at = 1:15, las = 2)
Explanation:
plot(..., yaxt = "n") means to not plot the y-axis ticks and labels, see ?par.
axis(...) adds an axis to a side. By itself, it will just add a default axis.
at= sets where the ticks and labels are placed.
labels= sets what to put at each tick. If absent (like it is above), it just prints the at value.
las=2 rotates the number so that it is perpendicular to the axis line. I did this to show more of the numbers, otherwise they will mask a bit more.
While this shows every-other, that is affected by the size of the canvas; if you do the same plot in full-screen, it'll show every number.
Related
I am plotting correlation coefficients (values = 0.0:1.0) for two isotopes measured in each individual from two populations. I would like to have a fixed aspect-ratio for my scatter-plot so that the x- and y-axis are exactly the same size no matter the graphics device. Suggestions?
This is my first plot in R, any comments on refinements to my code is appreciated? Finally, is it worth investing in learning the basic plotting techniques or should I jump right to ggplot2 or lattice?
My plot script:
## Create dataset
WW_corr <-
structure(list(South_N15 = c(0.7976495, 0.1796725, 0.5338347,
0.4103769, 0.7447027, 0.5080296, 0.7566544, 0.7432026, 0.8927161
), South_C13 = c(0.76706752, 0.02320767, 0.88429902, 0.36648357,
0.73840937, 0.0523504, 0.52145159, 0.50707858, 0.51874445), North_N15 = c(0.7483608,
0.4294148, 0.9283554, 0.8831571, 0.5056481, 0.1945943, 0.8492716,
0.5759033, 0.7483608), North_C13 = c(0.08114805, 0.47268136,
0.94975596, 0.06023815, 0.33652839, 0.53055943, 0.30228833, 0.8864435,
0.08114805)), .Names = c("South_N15", "South_C13", "North_N15",
"North_C13"), row.names = c(NA, -9L), class = "data.frame")
opar <- par()
## Plot results
par(oma = c(1, 0, 0, 0), mar = c(4, 5, 2, 2))
plot(1,1,xlim=c(0:1.0), ylim=c(0:1.0), type="n", las=1, bty="n", main = NULL,
ylab=expression(paste("Correlation Coefficient (r) for ", delta ^{15},"N ",
"\u0028","\u2030","\u0029")),
xlab=expression(paste("Correlation Coefficient (r) for ", delta ^{13},"C ",
"\u0028","\u2030","\u0029")))
points(WW_corr$South_N15, WW_corr$South_C13, pch = 23, cex = 1.25,
bg ="antiquewhite4", col = "antiquewhite4")
points(WW_corr$North_N15, WW_corr$North_C13, pch = 15, cex = 1.25,
bg ="black")
axis(1, at = seq(0, 1.0, by = 0.1), labels = F, tick = TRUE, tck = -0.01)
axis(2, at = seq(0, 1.0, by = 0.1), labels = F, tick = TRUE, tck = -0.01)
abline(h=.86, v=.86, col = "gray60", lty = 2)
legend("topleft", c("North", "South"), pch = c(15, 23),
col = c("black", "antiquewhite4"), pt.bg = c("black", "antiquewhite4"),
horiz=TRUE, bty = "n")
par(opar)
par(pty="s")
plot(...)
sets the plot type to be square, which will do the job (I think) in your case because your x and y ranges are the same. Fairly well hidden option documented in ?par.
Using asp=1 as a parameter to plot will get interpreted by the low-level plot.window call and should give you a unitary aspect ratio. There is the potential that a call using ylim and xlim could conflict with an aspect ratio scpecification and the asp should "prevail". That's a very impressive first R graph, by the away. And an excellent question construction. High marks.
The one jarring note was your use of the construction xlim=c(0:1.0). Since xlim expects a two element vector, I would have expected xlim=c(0,1). Fewer keystrokes and less subject to error in the future if you changed to a different set of limits, since the ":" operator would give you unexpected results if you tried that with "0:2.5".
I am having the following issue with the axis() function.
axis(1,
at=1:length(stringi::stri_rand_strings(21, 15)),
labels=stringi::stri_rand_strings(21, 15),
tick=1,
lwd=1,
mgp = c(0,1,0),
col = title_colour,
col.ticks = title_colour
,lty = "solid",
cex.axis = 1,las=2,cex=0.75)
But whatI really need are the tickmarks without the continuous x'x line connecting the ticks:
How do I accomplish this using axis()??
Set col to NA but col.ticks to a value:
plot(1, type = 'n', axes = FALSE)
axis(1, c(0.75, 1, 1.25), col = NA, col.ticks = 1)
(Note my reproducible and minimal example, try to include that in your question!)
When adding ticks to a plot (more ticks than default), how does one get the grid() to align the grid to the ticks?
plot(1:10,las=1,xaxp = c(0, 10, 10),xlim=c(0,10), ylim=c(0,10))
grid(lwd=2, nx=10, ny=10)
Tried changed the xlim and different numbers for the nx arg in grid (number of cells), but the grid simply doesn't line up.
Related, but doesn't answer question: Aligning grid lines in R, bReeze package
Related, and uses workaround: Align grid with ticks
Is the workaround the most efficient option?
You could use abline to draw grids. You can specify where the grids should be with h (for horizontal lines) and v (for vertical lines)
#Plot
plot(1:10,las=1,xaxp = c(0, 10, 10),xlim=c(0,10), ylim=c(0,10))
#Add horizontal grid
abline(h = c(0,2,4,6,8,10), lty = 2, col = "grey")
#Add vertical grid
abline(v = 1:10, lty = 2, col = "grey")
Another workaround is to use axis where tck value is 1. With axis, you can specify where the grids should be with at
#Plot
plot(1:10,las=1,xaxp = c(0, 10, 10),xlim=c(0,10), ylim=c(0,10))
#Add horizontal grid
axis(2, at = c(0,2,4,6,8,10), tck = 1, lty = 2, col = "grey", labels = NA)
#Add vertical grid
axis(1, at = 1:10, tck = 1, lty = 2, col = "grey", labels = NA)
#Add box around plot
box()
The problem is that grid is putting nx grid lines in the user space, but plot is adding 4% extra space on each side. You can take control of this. Adding xaxs="i", yaxs="i" to your plot will turn off the extra space. But then your upper right point will be cut off, so you need to change the xlim and ylim values and change nx to match. Final code is:
plot(1:10,las=1,xaxp = c(0, 10, 10),xlim=c(0,11), ylim=c(0,11),
xaxs="i", yaxs="i")
grid(lwd=2, nx=11, ny=11)
The answer to your question
When adding ticks to a plot (more ticks than default), how does one get the grid() to align the grid to the ticks?
is:
Using function axis to obtain the x axis tick locations created by plot function in combination with abline
Concretely, you substitute the line
grid(lwd=2, nx=10, ny=10)
by the following three lines
x_ticks <- axis(1, 0:10, labels = FALSE)
grid(lwd = 2, ny = NULL, nx = NA)
abline(v = x_ticks, lwd = 2, lty = 3, col = "lightgray")
and the result will be
You can control both x ticks and y ticks and get rid of the grid function. In this case the 3 lines would be
x_ticks <- axis(1, 0:10, labels = FALSE)
y_ticks <- axis(2, labels = FALSE)
abline(v = x_ticks, h = y_ticks, lwd = 2, lty = 3, col = "lightgray")
I would vote for the workaround. Because if you look at manual from ?grid, it has this statement,
"Note: If more fine tuning is required, use ‘abline(h = ., v = .)’
directly."
I need to put 2 columns of plots side by side (only one row in the example) and I can't manage to control the size of the plots and the position of the labels so that both plots are exactly aligned. This is the code the have now:
split.screen(c(1,2))
screen(1)
par(oma=c(0,1,0,0), mai=c(0.6,0.36,0.5,0.7), cex=0.5, mgp = c(0.5,0.1, 0), tck = -0.05)
plot(datos$UN.CJF*1000, datos$Methane.Produced.CJF, pch = 16, cex = 0.5, col ="black",
xlab = "UN (g/d)", ylab = expression('CH'[4]*'(g/d)'))
title(main = "a)", cex=0.8, line=0.5, adj=0, cex.lab=1.2)
datos$LWchangeD.CJF <- datos$LWchange.CJF/15
screen(2)
par(oma=c(0,1,0,0), mai=c(0.6,0.36,0.5,0.7), cex=0.5, mgp = c(0.5,0.1, 0), tck = -0.05)
scatter2D(datos$UN.CJF*1000, datos$Methane.Produced.CJF,
pch = 16,
xlab = "UN (g/d)", ylab = "",
colvar = datos$LWchangeD.CJF, clab = c("Liveweight change (kg/d)")
)
title(main = "b)", cex=0.8, line=-0.7, adj=0, cex.lab=1.2)
Notice how the size of the 2 figs is different
There must be a better way to do it.
Any help would be MUCH appreciated
Alvaro
grid.arrange did the trick, but I first re-did all my plots in ggplot2.
Thanks a lot for your suggestions
Alvaro
My problem concerns the making of a graph for a publication in R. I have used the plot function like follows:
plot(x=data$SL, y=data$BD, xlab = "SL (mm)", ylab = "BD (mm)", pch=data$pch)
SL ranges from 51.7 to 73.7 and BD from 13.5 to 20.4. Unfortunately I am not allowed to post images yet.
However, wanting to get rid of the box I used "axes=F". Problem now is lack of control over the axis function. I used:
axis(side=1, lwd=3, xpd=TRUE, at=c(min(data$SL):max(data$SL)))
axis(side=2, lwd=3, xpd=TRUE, at=c(min(data$BD):max(data$BD)))
Problem is that I can't manage to get the y- and x-axis to come together on the same point as in the plot with the box. How to let the x- and y- axis to touch each other?
Most likely setting xaxs = "i" and yaxs = "i" will help you getting the desired behaviour.
plot(c(1,2,3),c(2,4,6),axes=F,xaxs = "i",yaxs="i",xlim=c(0,3),ylim=c(0,6))
axis(side=1, lwd=3, xpd=TRUE, at=0:3)
axis(side=2, lwd=3, xpd=TRUE, at=seq(0,6,2))
Try box(bty='L') to draw only the left and bottom parts of the box. You could also just draw the lines yourself using lines, segments, or abline and using grconvertX and grconvertY functions to find the locations where to draw the lines.
I suggest that you follow the procedure you outlined and then use:
box(which = "plot", bty = "l")
e.g.:
plot.new()
plot.window(xlim = c(1, 18), ylim = c(2, 20))
points(1:18, 2:19, pch = 1, col = "#FF7F24", cex = 1.2)
lines(1:18, 2:19, col = "#FF7F24", lwd = 2)
axis(side = 1,
lwd = 0,
lwd.ticks = 1,
at = 1:18,
cex.axis = 0.9)
title(main = "Plot",
ylab = "Y-Axis")
legend("top",
legend = c("Legend"),
col = c("#FF7F24"),
text.col = c("#FF7F24"),
pch = 1,
bty = "n",
cex = 1.2)
axis(side = 2,
lwd = 0,
lwd.ticks = 1)
box(which = "plot", bty = "l")
You should pass the options lwd = 0 and lwd.ticks = 1 to your seperate axis() calls in order to prevent some parts of your axes to appear fatter than other parts of your axis because some get overlayed by your call to box() and some do not.
The solution of using box() at the end is, I think, more general in that you can use it when e.g. you cannot or do not want to pass bty = "l" in your plot.default or plot.window call.