I have created a stripchart in R using the code below:
oldFaithful <- read.table("http://www.isi-stats.com/isi/data/prelim/OldFaithful1.txt", header = TRUE)
par(bty = "n") #Turns off plot border
stripchart(oldFaithful, #Name of the data frame we want to graph
method = "stack", #Stack the dots (no overlap)
pch = 20, #Use dots instead of squares (plot character)
at = 0, #Aligns dots along axis
xlim = c(40,100)) #Extends axis to include all data
The plot contains a large amount of extra space or whitespace at the top of the graph, as shown below.
Is there a way to eliminate the extra space at the top?
Short Answer
Add the argument offset=1, as in
stripchart(oldFaithful, offset=1, ...)
Long Answer
You really have to dig into the code of stripchart to figure this one out!
When you set a ylim by calling stripchart(oldFaithful, ylim=c(p,q)) or when you let stripchart use its defaults, it does in fact set the ylim when it creates the empty plotting area.
However, it then has to plot the points on that empty plotting area. When it does so, the y-values for the points at one x-value are specified as (1:n) * offset * csize. Here's the catch, csize is based on ylim[2], so the smaller you make the upper ylim, the smaller is csize, effectively leaving the space at the top of the chart no matter the value of ylim[2].
As a quick aside, notice that you can "mess with" ylim[1]. Try this:
stripchart(oldFaithful, ylim=c(2,10), pch=20, method="stack")
OK, back to solving your problem. There is a second reason that there is space at the top of the plot, and that second reason is offset. By default, offset=1/3 which (like csize) is "shrinking" down the height of the y-values of the points being plotted. You can negate this behavior be setting offset closer or equal to one, as in offset=0.9.
I'm trying to visualise missing data with the R package VIM.
I'm using R version 3.4.0 with RStudio
I've used the function aggr() but the colnames of my dataframe seem to be too long. Thus, some labels of the x axis don't appear.
I would like to increase the space at the bottom of the x axis.
library(VIM)
aggr(df)
Here is my dataframe df and the plot I obtain
I've tried with par() function but it doesn't change anything.
aggr(df,mar=c(10,5,5,3))
or
par(mar=c(10,5,5,3))
g=aggr(df,plot=FALSE)
plot(g)
I can reduce the font size with cex.axis but then labels are too small.
aggr(df,cex.axis=.7)
Here is the plot with small axis labels:
I've not find a lot of examples using aggr() that's why I ask for your help.
Thank you in advance.
I think you are looking for a graphical parameter oma which will allow you to resize the main plot. The help reference states:
For plot.aggr, further graphical parameters to be passed down. par("oma") will be set appropriately unless supplied (see par).
In your case you could do something like:
aggr(df, prop = T, numbers = F, combined = F,
labels = names(df), cex.axis = .9, oma = c(10,5,5,3))
Obviously, you need to play around with cex.axis and other parameters to find out what works best for your data.
My code:
plot(factor(tData$Interval), tServiceLev, col = "red", type = "l", main =
'Service Level and Call Volume', xlab = "Time Intervals", ylab = "Service Level")
lines(factor(tData$Interval), tServiceLev, type = "l", col = "blue",lwd = 2)
par(new=TRUE)
plot(factor(tData$Interval), tData$Offered, type = "l", axes=FALSE, col = "green")
axis(4)
mtext("Call Volume", 4,1.5)
lines(factor(tData$Interval), tData$Offered, col = "red", lwd=2)
legend("topright", col=c("blue","red"), lty = 1, legend = c("Service Level", "Call Volume"), cex = .85)
When I put on the second plot, it overwrites the left axis completely. Also is there a way to make the actual graph larger and the axis labels closer to the axis range values?
Edit: This is my new graph after I knitted rmd. Call Volume is cut off. I want the time intervals to be as shown, but coloring each data point does not work. I guess part of the confusion is working with factored data which I've never worked with before.
Within the plot() calls, you need to set axes=FALSE. Then you can use axis() subsequently to customize the axes as you wish (using side=1 for bottom, side=2 for left axis).
For the other adjustments, try preceding plot with a call to dev.new(width=8, height=8), for example, launching an 8" by 8" device. Then using par(mai=c(2,2,1,1)) you can set 2" margins at bottom and left, 1" at top and right. Adjust those numbers as needed to get the proper size.
When calling axis, use axis(..., labels=FALSE) to make the axis with ticks, etc. Then print the actual labels using mtext. The lines=.. option within mtext will allow you to set the distance off the axis that the labels plot.
Update: Again, have you tried setting more space for the margin using par(mai=c(bottom,left,top,right)) as I suggested above? Using a larger number for right should give more space for the axis label. Also, try using type='o' to plot makers and lines. Still not understanding the change you'd like to make to the x axis.
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".
I use the gplots package to output barplots. I use it inside a for-loop, so rest of the code is omitted to make it more clear:
library("gplots")
pdf(file = "/Users/Tim/desktop/pgax.pdf", onefile = TRUE, paper = "special")
par(mfrow = c(4,2)) #figures arranged in 2 rows and 2 columns
par(las=2) #perpendicular labels on x-axis
barplot2(expression,ylab = expression(expression),main = graph.header, cex.names =0.85, beside = TRUE, offset = 0, xpd = FALSE,axis.lty = 0, cex.axis = 0.85, plot.ci = TRUE,ci.l = expression - sd.value, ci.u = expression + sd.value, col = colors,width = 1,names.arg = c(etc))
Now when I specify the papersize at a4, and print out in two columns the bars are made so they fill up the full space assigned. If I only have a few bars in each graws, the width is too big compared to the height. I know I should be using xlimit and width = amongst and perhaps even the aspect ratio?, but I can't get the results I wanted. And unconvenient way is to specify the height and width output of the paper, and manually I adjust it for the number of bars in the plots each time. But this doesnt seem appropiate. Does someone know a convenient way to fix width bars in my plots?
All help is much appreciated!
Although bar plots with wide bars can look silly, a wide bar plot with a few narrow bars in it will likely look even sillier. That leaves you specifying the width of the plot (via the width argument to pdf).
It may be prettiest to keep all your plots the same size, in which case you just give width a fixed value. If you do want narrower plots when there are less bars, you need a line of code like
plot_width <- 3 + 0.5 * nlevels(x_variable)