Set different positions of axis labels and tick marks in a barplot - r

I would like to realign/offset the x-axis and associated tick marks of a barplot. This should be simple but I am having trouble finding an answer. Below is some example data with 24 categories.
xval = c(1:24)
count = c(0.03,0.03,0.08,0.06,0.11,0.4,0.3,0.5,0.5,0.6,0.4,0.1,0.1,0.4,0.2,0.1,0.06,0.05,0.03,0.02,0.01,0.03,0.01,0.02)
df = as.data.frame(cbind(xval, count))
I can easily produce a barplot with tick marks aligned at the bar midpoints using the below code:
mp <- barplot(df$count, space=0, axes=FALSE)
axis(side=2, pos=-0.2)
axis(side=1, at =mp, labels=df$xval)
I can also shift the entire x-axis (labels and ticks) to align with the outside of bars using the below (although this now fails to incorporate the last bar into the axis):
axis(side=1, at =mp-0.5, labels=df$xval)
While I would like the x-axis and associated tick marks to be aligned with the bar boundaries (i.e. a tick mark on either side of the bar instead of in the centre), I want the x-axis labels to remain at the bar midpoints. Is there an easy way to achieve this?

Is this what you are looking for?
# create positions for tick marks, one more than number of bars
at_tick <- seq_len(length(count) + 1)
# plot without axes
barplot(count, space = 0, axes = FALSE)
# add y-axis
axis(side = 2, pos = -0.2)
# add x-axis with offset positions, with ticks, but without labels.
axis(side = 1, at = at_tick - 1, labels = FALSE)
# add x-axis with centered position, with labels, but without ticks.
axis(side = 1, at = seq_along(count) - 0.5, tick = FALSE, labels = xval)

Related

R Barplot: Y-axis cut off at the top?

I'm trying to use R to do a barplot. Values I'm plotting range from 0 to 5.0, but are decimal values (such as 4.87) so I don't want to just use the default Y axis, because it just goes up in increments of 1.
I've created a custom Y axis, which works, but if I set the maximum value greater than about 4.5, it cuts off the tickmark at the top of the axis. This looks untidy so I want a way to ensure this tickmark will always appear, but I don't want to shorten my axis as it looks stupid if I do this.
My R code is as follows:
# Bar plot of mean SUS question scores
barplot(meanSUSQuestions$Mean,
main="Mean SUS Question Scores",
cex.main="0.8",
cex.axis="0.8",
cex.lab="0.8",
#names=c("q1", "q2", "q3","q4","q5","q6","q7","q8","q9","q10"),
names=c(1:10),
yaxt="n",
col="red")
axis(2, cex.axis="0.8", at=seq(0, 5, 0.5)) # Create custom Y axis
mtext(text="Mean Score", side=2, line=2, cex=0.8)
mtext(text="Question", side=1, line=2, cex=0.8)
The bar plot that this produces looks like this:
As you can see from the picture, the top tickmark is missing.
How can I get this top tickmark to appear?
barplot generates the image height based on the data. The range of your manual y-axis is considerably larger than the plot area and is thus cut off.
The easiest way to solve the issue in your specific case is to add an yaxp = c(0, 5, 11) to barplot instead of yaxt = "n" and axis.
A self-contained example:
# Bad
x <- 1:5
barplot(x, yaxt = "n") #, add = TRUE)
axis(2, at = seq(0, 6, 2)) # Create custom Y axis
# Good
barplot(x, yaxp = c(0, 6, 2))

Put tick labels of only x-axis inside plotting area

Is it possible to put tick labels of only x-axis inside plotting area?
I am trying:
axis(1,at=c(0:71),c(rep(0:23,3)),cex.axis=.7, font=1,tck=.01)
It seems that:
par(mgp=c(0,-1.4, 0))
puts both x and y tick labels inside plotting area.
Why don't you just draw the ticks where you want them using the pos argument to axis():
plot(0:72, xaxt="n")
text(0:71, -1, rep(0:23, 3), cex = 0.5)
axis(1, at=c(0:71), NA, cex.axis=.7, font=1, tck=.01)
I think the best and easy solution is the parameter tcl in axis or par.
Positive values put the marks inside, negative outside, the value is the length.
Your example:
axis(1,at=c(0:71),c(rep(0:23,3)),cex.axis=.7, font=1,tcl=0.3)

Use axis() to draw axis without ticks

Given a plot without axes, I would like to use axis to add a horizontal axis. On the left hand side you see the given "baseline" plot, on the right hand side the desired result:
The baseline plot is simply generated using
plot(1, axes = FALSE, main = "Baseline")
Question: How to generated the desired output? (Condition: using axis after the plot has been generated.)
I expected that I get what I want when specifying tick = FALSE, labels = FALSE, but this doesn't work. Below my tests, hopefully self-explanatory:
par(mfrow = c(2,2))
plot(1, axes = FALSE, main = "Full axis")
axis(1) # axis, ticks and labels
plot(1, axes = FALSE, main = "No labels")
axis(1, labels = FALSE) # axis, ticks
plot(1, axes = FALSE, main = "No ticks (and no axis)")
axis(1, tick = FALSE) # NO axis (unexpected), labels
plot(1, axes = FALSE, main = "Nothing (instead of axis)")
axis(1, tick = FALSE, labels = FALSE) # nothing - expected: only axis without ticks, without labels
I expected the last plot to deliver the desired output, but the axis is not drawn at all. Apparently, ticks = FALSE suppresses the axis itself as well.
Remark: The "expected" plot was generated using
plot(1, axes = FALSE, main = "Expected")
axis(1, at = c(-100, 100))
but I am looking for a "cleaner" solution than placing unwanted ticks outside the visible area.
Other workarounds are axis(1, lwd.tick=0, labels=FALSE), axis(1, tcl=0, labels=FALSE), which draw 0 width or 0 length ticks, respectively. #LyzandeR's solution seems to draw white ticks on top of the axis. The proposed box() solutions and ?par don't seem to draw just the X axis?
This seems to plot what you want:
plot(1, axes = FALSE, main = "No labels")
axis(1, label=F, col.ticks='white') # axis, ticks
It just prints the ticks as white:

Centring bar labels in bar plots in r

How can I centre the labels on the x-axis to match up with the bars? Also, how can I position the x axis label further down so it it is not obscured by the x-axis labels? Thanks!
par(mar= c(15,4,4,2) + 0.1)
barplot(58:1,xaxt="n",xlab="",ylab="Frequency", col=gray(5:0/5))
axis(1, labels=FALSE)
text(1:58, par("usr")[3] - 0.25, srt = 90, adj = 1,
labels = rep("Long Species Name",58), xpd = TRUE)
mtext(1, text = "Species", line=6)
Check out the return value of barplot() (by reading ?barplot). There we find that the mid points of the bars are returned by the function as a vector. Hence it is a simple matter of assigning the returned object (here to object bar) and then use that in a call to axis() to locate the tick marks.
In the axis() call, note that we specify both the labels argument and the at argument, with at being set to the bar mid points as stored in bar. las = 2 is used to rotate the labels relative to the axis, and cex.axis = 0.6 is used to reduce the label size.
The second part of your question is handled by title() and the line argument. First note that when you set the mar parameter you are setting the margin size in "lines", hence the margin on side 1 (bottom) is 15 lines. The line argument in title() specifies which of the margin lines you want to draw the axis label.
Putting this altogether with a modified example we have:
op <- par(mar= c(15,4,4,2) + 0.1)
bar <- barplot(58:1, xaxt="n", xlab="", ylab="Frequency", col=gray(5:0/5))
axis(1, labels = paste("Long Species Name", 1:58), at = bar,
las = 2, cex.axis = 0.6)
title(xlab = "Species", line=11)
par(op)
Which produces:

Plot() command to move x-axis on top of the plot

I'm trying to move the x-axis labeling and tick marks above the plot on top. Here's my code.
ucsplot <- plot(ucs, depth, main= "Depth vs. UCS", xlab = "UCS (psi)", ylab="Depth (ft)", type="l", col="blue", xlim=c(0, max(dfplot[,3]+5000)), ylim = rev(range(depth)))
ucsplot
How do I get the x-axis labeling and tick marks to appear only on top, instead of the bottom? Also, how do I get the title to not sit right on top of the numbers right above the tick marks? Also, how do I get the chart to start not offset a little bit to the right? As in the zero and starting numbers are in the corners of the plot and not offset.
Seems the OP is looking for a plot where x-axis is at top. The data has not been provided by OP. Hence using a sample dataframe, solution can be displayed as:
df <- data.frame(a = 1:10, b = 41:50)
plot(a ~ b, data = df, axes = FALSE, xlab = NA, ylab = NA)
axis(side = 2, las = 1)
axis(side = 3, las = 1)

Resources