Labels Not Appearing After Sequence of Layouts R - r

I am running the following code:
par(bg="yellow", mar=c(2,2,2,2))
layout(matrix(c(rep(1,12),2:13),nrow=2,byrow=T),width=myWidth)
plot(days,sum_precip,type="l",xaxt="n",yaxt="n",ann=FALSE,
xlab="TEST",main="WEWQWE",ylab="dsads")
On the last statement, my plot fails to display any labels even after specifying this in arguments. Is it because my margins are too small?
I am trying to add a header for the x-axis for each of my graphs on the bottom row of the layout.
Example of Issue:
Note, I'm more curious about why this does not work. I know I can just specify an axis(..), but this is more out of interest.

Here a solution using mtext. see ?mtext
Text is written in one of the four margins of the current figure
region or one of the outer margins of the device region.
par(bg="lightyellow", mar=c(2,2,2,2))
layout(matrix(c(rep(1,12),2:13),nrow=2,byrow=T))
replicate(13,
{ plot(x=1:5,y=cumsum(1:5),type="l",xaxt="n",yaxt="n",ann=FALSE)
mtext(text='TEST',side=1,line=1)
mtext(text='dsads',side=2,line=1)
})
EDIT
You can set the margin for every plot.
par(bg="lightyellow", mar=c(2,2,2,0))
layout(matrix(c(rep(1,12),2:13),nrow=2,byrow=T))
for(i in 1:13){
if (i %in% 1:2){
plot(x=1:5,y=cumsum(1:5),type="l",xaxt="n",yaxt="n",ann=FALSE)
mtext(text='TEST',side=1,line=1)
mtext(text='dsads',side=2,line=1)
}else{
par( mar=c(2,0,2,0))
plot(x=1:5,y=cumsum(1:5),type="l",xaxt="n",yaxt="n",ann=FALSE)
}
}

Yeah margins are too small.
Example:
par(mar=rep(4,4))
plot(1, 1, xaxt='n', xlab='x', yaxt='n', ylab='y')
this shows the labels (sorry it's tiny).
However using par(mar=rep(2,4)):
The labels are cut off.
You can use the mgp argument to modify the offset (in lines) of the axis text from the axis. In particular (?par), mgp is a vector of length 3 where mgp[1] is the lines between the plot and axis label, mgp[2] is for the axis line itself and mpg[3] is for the axis tick labels.
So:
par(mar=rep(2,4))
# mgp[2:3] irrelevant in this case as we have turned
# axis line/ticks off; doesn't matter what they are set to
plot(1, 1, xaxt='n', xlab='x', yaxt='n', ylab='y', mgp=c(1,0,0))
This will place the axis labels 1 line away from the axis (i.e. on the second line away) which just fits into our margin of 2,2,2,2.

Related

R: two axes and grid lines

I would like to plot two graphs in the same plotting region with horizontal grid lines. Each side of the grid lines should give the value for one graph or the other. There should be no y-axis.
The grid() function allows me to simply set the number of bins using the ny= argument. How do I get the corresponding labels to the grid lines? Usually, I would use axis(..., lwd=0) to get the labels. However, the function requires label positions with at=c() and does not feature a ny= argument. Is there a way to automatically set the locations from the number of bins?
Based on Miff's hint below, this should solve the problem.
plot(1:10, axes=FALSE, ylim=c(0,10), ylab="")
par(yaxp=c(0, 10, 5))
axis(2, lwd=0, col.axis="gray")
par(new=TRUE)
plot(60:50, axes=FALSE, ylim=c(50,60), ylab="")
par(yaxp=c(50, 60, 5))
axis(4, lwd=0, col.axis="gray")
grid(NA, NULL)
grid() gets its locations for gridlines from axTicks(), which in turn uses numbers from par("yaxp"). If you modify this parameter (rather than explicitly passing it to grid), the result will then apply to both the grid drawn and the axis. For example:
plot(1:10, axes=FALSE)
axis(2) #Default 4 sections between ticks
par(yaxp=c(par("yaxp")[1:2], 7)) #Lets have seven instead
axis(4)
grid() #Grid now matches with right rather than left
Obviously similar works for the x axis.

Why is one number missing with barplot? [duplicate]

When I manually add the following labels with (axis(1, at=1:27, labels=labs[0:27])):
> labs[0:27]
[1] "0\n9.3%" "1\n7.6%" "2\n5.6%" "3\n5.1%" "4\n5.7%" "5\n6.5%" "6\n7.3%" "7\n7.6%" "8\n7.5%" "9\n7%" "10\n6.2%" "11\n5.2%"
[13] "12\n4.2%" ........
I get the following:
How do I force all labels to be drawn so 1,3,5,6, and 11 are not skipped? (also, for extra credit, how do I shift the whole thing down a few pixels?)
If you want to force all labels to display, even when they are very close or overlapping, you can "trick" R into displaying them by adding odd and even axis labels with separate calls to the axis function, as follows:
labs <-c("0\n9.3%","1\n7.6%","2\n5.6%","3\n5.1%","4\n5.7%","5\n6.5%","6\n7.3%",
"7\n7.6%","8\n7.5%","9\n7%", "10\n6.2%","11\n5.2%","12\n4.2%",13:27)
n=length(labs)
plot(1:28, xaxt = "n")
axis(side=1, at=seq(1,n,2), labels=labs[seq(1,n,2)], cex.axis=0.6)
axis(side=1, at=seq(2,n,2), labels=labs[seq(2,n,2)], cex.axis=0.6)
You can play with cex.axis to get the text size that you want. Note, also, that you may have to adjust the number of values in at= and/or labels= so that they are equal.
I agree with #PLapointe and #joran that it's generally better not to tamper with R's default behavior regarding overlap. However, I've had a few cases where axis labels looked fine even when they weren't quite a full "m-width" apart, and I hit on the trick of alternating odd and even labels as a way to get the behavior I wanted.
?axis tells you that:
The code tries hard not to draw overlapping tick labels, and so will omit labels where they would abut or overlap previously drawn labels. This can result in, for example, every other tick being labelled. (The ticks are drawn left to right or bottom to top, and space at least the size of an ‘m’ is left between labels.)
Play with cex.axis so that labels are small enough to fit without overlapping
labs <-c("0\n9.3%","1\n7.6%","2\n5.6%","3\n5.1%","4\n5.7%","5\n6.5%","6\n7.3%",
"7\n7.6%","8\n7.5%","9\n7%", "10\n6.2%","11\n5.2%","12\n4.2%",12:27)
plot(1:27,xaxt = "n")
axis(side=1, at=1:27, labels=labs[0:27],cex.axis=0.35)
If you widen you graph (manually by dragging or programmatically), you can increase the size of your labels.
Although there are some good answers here, the OP didn't want to resize the labels or change anything about the plot besides fitting all of the axis labels. It's annoying, since often there appears to be plenty of room to fit all of the axis labels.
Here's another solution. Draw the plot without the axis, then add ticks with empty labels. Store the positions of the ticks in an object, so then you can go through each one and place it in the correct position on the axis.
plot(1:10, 1:10, yaxt = "n")
axis_ticks = axis(2, axTicks(2), labels = rep("", length(axTicks(2))))
for(i in axis_ticks) axis(2, i)
#PLapointe just posted what I was going to say, but omitted the bonus answer.
Set padj = 0.5 in axis to move the labels down slightly.
Perhaps draw and label one tick at a time, by calling axis repeatedly using mapply...
For example, consider the following data:
x = runif(100)*20
y = 10^(runif(100)*3)
The formula for y might look a bit odd; it gives random numbers distributed across three orders of magnitude such that the data will be evenly distributed on a plot where the y axis is on a log scale. This will help demonstrate the utility of axTicks() by calculating nice tick locations for us on a logged axis.
By default:
plot(x, y, log = "y")
returns:
Notice that 100 and 1000 labels are missing.
We can instead use:
plot(x, y, log = "y", yaxt = "n")
mapply(axis, side = 2, at = axTicks(2), labels = axTicks(2))
which calls axis() once for each tick location returned by axTicks(), thus plotting one tick at a time. The result:
What I like about this solution is that is uses only one line of code for drawing the axis, it prints exactly the default axis R would have made, except all ticks are labeled, and the labels don't go anywhere when the plot is resized:
I can't say the axis is useful in the resized example, but it makes the point about axis labels being permanent!
For the first (default) plot, note that R will recalculate tick locations when resizing.
For the second (always labeled) plot, the number and location of tick marks are not recalculated when the image is resized. The axis ticks calculated by axTicks depend upon the size of the display window when the plot is first drawn.
If you want want to force specific tick locations, try something like:
plot(x, y, log = "y", yaxt = "n")
mapply(axis, side = 2, at = c(1,10,100, 1000), labels = c("one", "ten", "hundred", "thousand"))
which yields:
axis() includes a gap.axis parameter that controls when labels are omitted. Setting this to a very negative number will force all labels to display, even if they overlap.
The padj parameter of axis() controls the y offset whilst plotting an individual axis.
par(mgp = c(3, 2, 0) will adjust the position of all axis labels for the duration of a plotting session: the second value (here 2, default 1) controls the position of the labels.
# Set axis text position, including for Y axis
par(mgp = c(3, 2, 0))
# Plot
plot(1:12, 1:12, log = 'x', ann = FALSE, axes = FALSE)
# Some numbers not plotted:
axis(1, 1:12)
# All numbers plotted, with manual offset
axis(1, 1:12, gap.axis = -100, padj = 0.5)
I had a similar problem where I wanted to stagger the labels and get them to print without losing some. I created two sets of ticks showing second set below the other to make it look as if it staggers.
xaxis_stagger = function(positions,labels) {
odd=labels[seq(1,length(labels),2)]
odd_pos=positions[seq(1,length(positions),2)]
even=labels[seq(2,length(labels),2)]
even_pos=positions[seq(2,length(positions),2)]
axis(side=1,at=odd_pos,labels=odd)
axis(side=1,at=even_pos,labels=even,padj=1.5)
}
So you give the positions where you want the ticks to be and the labels for those ticks and this would then re-organise it into two sets of axis and plot them on the original plot. Original plot would be done with xaxt="n".

R: combine mtext() with points() - correct way to specify coordinates?

I want to combine a text I place in the margins with mtext() with a graphics object that I create either using points() or polygon(). The following example roughly works for me with the default plot settings:
plot(1)
mtext("This is a red dot:", side=1, line=2, cex=0.8)
par(xpd=T)
points(1.08, 0.512, pch=15, cex=1.5, col="red")
However, using plot(1:10) instead or prefixing it with windows(8,8) puts the dot in the wrong position, as points() takes user coordinates. Is there a way to get my dot placed correctly independent of plot limits or device size?
I think I have found an answer that works based on the suggestions of #koekenbakker. To make it look pretty, some minor adjustments are still necessary to get the dot in line with the text, but it seems to work well independent of plot size and axis limits (but you cannot resize the plot once created). To do the adjustments on the exact position of the point, I would recommend using fractions of strheight("O", cex=0.8) and strheight("O", cex=0.8) for this example (which uses cex=0.8 for demonstration).
plot(1)
mtext("This is a red dot:", side=1, line=2, cex=0.8, col="green") ## place sample text at bottom of figure
par(xpd=T) ## enable plotting outside plot region
textXPos <- mean(par("usr")[1:2]) ## x position is middle of plot
textYPos <- par("usr")[3] - strheight("O") * 4 ## y position is below bottom of plot (line 2 = 4 * height of letter O)
text(textXPos, textYPos, "This is a red dot:", cex=0.8, col="red", adj=c(0.5, 0)) ## this text overlaps - y position is correct
pointXPos <- textXPos + 0.5 * strwidth("This is a red dot:", cex=0.8) ## text is centred, so need to move half of the text width to the right
points(pointXPos, textYPos, pch=16, col="red") ## still needs minor adjustments to x and y position to make it look nice

R: How do I position multi-line tick labels at plots in base R?

In base R plots, I would like to attach multi-line labels to the ticks. Here is a test case, first with simple single-lined labels:
# plot some graph
x = (-10:10)/5
y = x^2
plot (y~x,type="l",axes=F)
ticks = c(-2,-1,0,1,2) # tick positions
labels = c("-2","-1","0","1","2") # tick labels
axis (1,at=ticks,labels=labels)
Now I would like to have some labels extend over several lines of text. When I use
labels = c("-2","-1","centre\n0","1","2") # some tick labels multi-line
the second line of the label is added above the existing labels, leaving insufficient space between the axis and the labels. The tick labels are aligned at the bottom.
How (1) do I have them aligned at the top or; (2) can I move all tick labels down in order to get more space between the axis and the labels?
Thanks in advance for your help!
I always find it easier to plot the second line as a new plot on top of the previous one. There is a problem with your data as I see it. I don't really know which is your intention but I will explain the method in detail below.
My problem is that your second labels are the same as the first apart from the word 'centre' which you add in at x=0. Therefore, in my case I have created a new label variable which will only have the second line elements i.e. only the word 'centre' with everything else being blank.
Data
This is your data
# plot some graph
x = (-10:10)/5
y = x^2
plot (y~x,type="l",axes=F)
ticks = c(-2,-1,0,1,2) # tick positions
labels = c("-2","-1","0","1","2") # tick labels
axis (1,at=ticks,labels=labels)
Solution1
Aligned at the bottom properly:
In this case I create a new plot that will have a longer bottom margin. Then I create only a bottom axis for that and set it to colour white so that only the labels are visible:
#bottom
#new plot
par(new=TRUE)
#new margins. default is c(5,4,4,2).First value is the bottom margin.
par(mar=c(4,4,4,2))
#new labels
labels = c("","","centre","","") # some tick labels multi-line
#make the axis
axis (1,at=ticks,labels=labels, col='white')
If you need centre and zero to be plotted the other way round just change the labels.
Solution2
Aligned at the top properly (if I get what you mean):
In your data axis needs to be: axis(3,at=ticks,labels=labels). The three there shows it should be aligned on top
The logic is the same as previously but you need to change the corresponding margin i.e. the third value:
#top
par(new=TRUE)
par(mar=c(5,4,3,2))
labels = c("","","centre","","") # some tick labels multi-line
axis (3,at=ticks,labels=labels, col='white')

R: Two axis chart adjustments

I am trying to plot a chat with two axis, here is the code and attached is the plot,
I have to do two adjustments to it.
I want to plot a line with dots and dots should be middle of the bars
Adjusting right side axis(i.e axis(4)) tick marks should align with left side axix(i.e axis(2))
Code:
Region=c("North","South","East","West")
Sales=sample(500:1000,4)
Change=sample(1:10,4)/10
names(Sales)=Region
names(Change)=Region
barplot(Sales,ylim=c(0,1000))
par(new=T)
plot(Change,type="b",axes=F,ylim=c(0,1))
axis(4)
box()
Regards,
Sivaji
First, save your barplot as some object. So you will get coordinates of the middle points. Then to add line you can use also function lines() and just multiply Change values with 1000.
Then for axis() function supply at= values and labels= the same as at=, just divided by 1000.
x<-barplot(Sales,ylim=c(0,1000))
lines(x,Change*1000,type="b")
axis(4,at=seq(0,800,200),labels=seq(0,800,200)/1000)
You need to play to set the same x-axis in the second plot, you get this info from par("usr").
The xaxs="i" is to set the xlim exactly, by default R increase the xlim a bit to make it better looking.
par(mar=c(5,5,2,5)) # change margins
x = barplot(Sales, ylim=c(0,1000)) # barplot, keep middle points of bars
mtext("Sales", 2, line=3) # first y-axis label
xlim = par("usr")[1:2] # get xlim from plot
par(new=TRUE)
plot.new() # new plot
plot.window(xlim=xlim, ylim=c(0,1), xaxs="i", yaxs="i") # new plot area, same xlim
lines(x,Change,type="b") # the lines in the middle points
axis(4) # secondary y-axis
mtext("Change", 4, line=3) # secondary y-axis label
box()

Resources