R/Zoo: show a tick every year on x-axis - r

I've a zoo object, with a yearqtr index, covering about 50 years. When plotted the x-axis shows labels every 10 years, which feels a bit barren:
b=zoo(1:200,as.yearqtr(1900+seq(1,200)/4))
plot(b)
Some study got me this:
plot(b,xaxt="n");axis(1,time(b))
Which feels like swinging from one extreme to the other, as the x-axis is a blur of ticks, with ugly fractional labels. Is there an easy way to have it just show years? (What I was looking for initially was a way to say: "lower the x-axis label spacing a bit", but there seems nothing like that? cex.axis just alters the font-size.)

Did you read help(axis)?
Here is one way, just creating a simple index every four quarters:
R> ind <- seq(1, length(b), by=4)
and using it to index the axis placement and labels:
R> plot(b,xaxt="n")
R> axis(1,time(b)[ind], format(time(b)[ind]), las=2, cex.axis=0.5)
I used las=2 and the lower cex value to make this fit. Once every year may still be too plenty.
Computing "good" axis labels is really hard.

This is probably one of those (rare) situations when you want to use grid rather then ticks to better show your data. As #dirk-eddelbuettel pointed out - tweaking good axis labels is hard, especially with such density. You also might want your labels inside plot, so the grid will slightly hide their density. The easiest grid to get is with abline, unless you want to play with ggplot2, but it's uglier then standard plots in R (personal opinion). Also - make the plot wider. In fact, it's better to get rid of box around plot too ;) Below is mod of Dirk's approach:
png("strangeplot.png",width=800)
#extend y-axis to fit inside labels and remove box
plot(b,type="n",xaxt="n",yaxt="n",ylab="",xlab="",ylim=c(min(b)-30,max(b)),bty="n"))
#use 'mpg' to get labels inside
axis(1,time(b)[ind], format(time(b)[ind]), las=2, cex.axis=0.6,tick=F,mgp=c(0,-2.5,0))
axis(2,tick=F,las=1)
#you locate lines slightly to the left of label...
abline(h=seq(0,200,by=50),v=time(b)[ind]-0.5,col=gray(0.9))
#...so you need to add extra single line in the end
abline(v=max(time(b)[ind])+0.5,col=gray(0.9))
#plot at the end to get it above grid
points(b,type="l")
dev.off()

Related

Decorana on R and using xlim

So I've been running a DCA analysis on a species/site count spreadsheet (DCA file made using Vegan and decorana command). I'm having a bit of overlap with my points, so I'm trying to extend DCA 1 axis. I keep trying to use the xlim value to narrow it down to -2,2, but it just won't do it. For some reason, it seems tied to the ylim value. If I drop the ylim to -1,1, that will force the xlim to -2,2, but I can't actually have the ylim that small.
> plot(DCA, type = "n", xlim = c(-2,2))1
First plot shows result of this command. Trying to include a ylim of (-2,2) didn't change it either. Second plot shows result of this command:
> plot(DCA, type = "n", xlim = c(-2,2)), ylim = c(-2,2)2
I'm not exactly an expert at this, and I feel like I might be making a stupid mistake. Anyone got any ideas?
The plot is enforcing equal aspect ratio, and if you insist on having full range on y-axis (you do not set ylim), the x-axis will be set to accommodate the range you want to show on y-axis. You must either change the shape of your graphics display for a shorter x-axis, or then you also must set the range on y-axis with ylim Your choice. If you draw on square graphics window, the output will be square and it will be taken care that both the x and y scale (xlim, ylim) will fit the square. Changing the shape of the graphics window or setting both limits will help. Function locator() can be used to query coordinates in an existing plot, and these can be used to set up the new limits.
It is better to start again from a clean table. My intention was not to be rude, but trying to complement the answer in comments leads into terse messages where details and special cases are hard to handle. So I try to explain here how you can control the display and the axis limits in vegan ordination graphics. This answer has two main parts: (1) why we insist on equal aspect ratio, and (2) how to survive with equal aspect ratio. The latter can indeed be tricky, but we have not made it tricky because we are evil, but it is necessarily tricky.
First about the equal aspect ratio. This means that the numeric scales is equal on vertical (y) and horizontal (x) axes. In ordination the "importance" of an axis is normally reflected by its length: important axes are long, minor axes are short. In eigenvector methods this is determined by eigenvalues (which actually define the scatter of points along axes). In DCA (decorana) it should be the SD scaling so that one unit is equal to average width of species responses. We pay great attention in scaling axes accordingly, and we want to show this in the plot so that long x axis remains long and short y axis remains short even when the graph is designed for a portrait printer page shape. In this way the axis scaling (tic values) are equally spaced on both axes, and distances in the graph are equal horizontally, vertically or diagonally. Also if you draw a circle in the plot, it will remain a circle and not flattened or elongated to an ellipse. So this is something that we insist as a necessary feature of an ordination graph.
Insistence on equal scaling of equal axes comes with a price. One obvious price is that the ordination plot may not fill the graph area, but there can be a plenty of empty space in the graph for shorter axes. You can get rid of this adjusting graph shape – typically making it flatter. Another price that must be paid is the one that bit you: setting axis limits is tricky. However, this is not a vegan invention, but we use base R plot command with option asp = 1 for equal aspect ratio of axes.
To see how we can set axis limits with equal ratio, let us generate a regular rectangular grid and plot it:
x <- seq(-2, 2, by=0.2)
xy <- expand.grid(x, x)
plot(xy, asp=1)
This is a square grid on a square plot and nothing very special. However, if we plot the same grid on rectangle the aspect ratio remains equal, numeric scales are equal and the points remain equidistant on a square, but there is a lot of empty space and x-axis has longer numeric scale (but the points have unchanged numeric scale). If we try reduce only the x-scale, we face a disappointment:
plot(xy, asp=1, xlim=c(-1,1), main="xlim=c(-1,1)")
The graph is essentially similar as the first unlimited case with unchanged x. Setting xlim does not remove any points, but it only tells plot that do not reserve space but for that range on x-axis. However, y-scale is still longer and with equal aspect ratio it will also set the scale for x-axis and since there is empty space in the graph, the points are plotted there (this is analogous to having empty space even when there is nothing to plot there). To really limit the x-axis, you must simultaneously limit the y-axis accordingly:
plot(xy, asp=1, xlim=c(-1,1), ylim=c(-1,1), main="xlim=c(-1,1), ylim=c(-1,1)")
This give the desired x-limits .
Like I wrote, we did not invent that nastiness, but this is base R plot(..., asp=1) behaviour. I know this can be tricky (I have used that myself and sometimes I get irritated). I have been thinking could we be more user-friendly and by-pass base R. It is pretty easy to do this in a way that works in many normal use cases, but it is much harder to do this so that it works in most cases, and I don't know how to do this in all possible cases. If anybody knows, pull requests are welcome in vegan.
Finally, there is one tool that may help: vegan has an interactive dynamic plotting tool orditkplot where you can zoom into a plot by selecting a rectangle with left mouse button. However, this function may not work in all R systems, but if it works it gives an easy way of studying details of the plot (but if you have Mac with one-button mouse, don't ask me how it works: I don't know). You can start this with
orditkplot(mod, display="sites") # or "species", but only one
Even without orditkplot you can use base R function locator(): click the diagonally opposite corners of the rectangle you want to focus on, and this give you the xlim and ylim you need to set to zoom into this rectangle.

How to plot just one axis label in R?

A beginner question: I currently have some plots that look like this.
I'm keeping the plots free of other annotation because I have to fit a lot of them onto one page and specific values aren't important, just the general trend that the red line is to the right of the black one. However, I'd like to be able to indicate that the dashed line in my plot actually represents zero, like so:
Is there any way to tell R to only display that value on the x-axis labels? I don't think using text() would be a good idea because it relies on absolute coordinates, but I'm not really sure how to work with axis options to make it do what I want.
Try:
axis(side = 1, at = 0)
See ?axis for details.

Intelligent Y Axis Scaling BarPlot R

I want to plot some data with barplot. Rather, I want to make a bar graph and barplot seemed the logical choice. I am plotting just fine but I was wondering if there is a way to intelligently scale the y axis to round up from the highest count.
For example I set the yaxis in this case to be 30, because I knew that Strand.22 had 27 counts in it: barplot(unlist(d), ylim=c(0,30), xlab="Forward Reverse", ylab="Counts")
In the future, I want this script to run on its own, so it would be optimal for the the Y-axis to choose it's own ylim. Short of pulling the information out of my 'd' variable I can't think of a good way to do this. Is there an easy way to do this with barplot? Would some other plotter work better? I have seen things about ggplots but it seemed super complex and I wasn't sure that it would do anything better.
EDIT: If I do not choose a ylim it picks automatically and this is what it decided was best.
I disagree with it's choice.
If you don't specify ylim, R will come up with something based on the data. (Sounds like you don't like it's choice, which is fair.)
If you specify something based on the data like:
barplot(unlist(d), ylim=c(0,1.1*max(unlist(d)))
R will draw you a plot that reflects the maximum value of data. That example just takes the maximum of your values and multiplies that by 1.1 (this could be any number) to give it a little extra height. R does something similar to this when you make a scatterplot but it handles barplots slightly differently.

Axis automatically changed?

I have a plot, where the lines are only in the negative range and when I plot it, the axis is automatically changed, i.e. negative larger values are going up and not down, in a normal plot. Currently I have the following plot:
But I want to have the y axis the other way round, so that negative larger values are going down and not up, I hope it is understandable what I mean.
How can I achieve this in R?
My code with my specific data is just using the normal plot() function.
As Ben Bolker said, the following has to be said:
I set the ylim range wrong, I set it like
ylim=c(-0.05,-1)
but
ylim=c(-1,-0.05)
should do what I want!

Horizontal grid not matching y axis ticks

I have the following data:
x=c(2.880262,3.405859,3.613575,3.744480,3.682059,3.694075,3.758320,4.034290,4.202741,4.309383,4.996279,5.981309,5.103148,4.926363,4.696024,5.522913,5.330382,4.434304,5.154567,6.247156,8.612752,9.996526,9.606994,10.303496,5.954970,5.688171,6.340349,6.252854,6.355642,5.988570,7.317148,11.664384,14.231579,16.489029,23.100640,20.280043,21.562793,24.311327,23.735198,23.796386,23.118181,23.269722,19.886981,20.000975,19.967642,24.278910,17.447721,14.536114,20.646378,19.096832,20.258060,19.803196)
y=1:52
w=c(-2784,-2897,-2897,-2066,-2466,-2466,-2466,-2466,-2102,-2102,-2102,-2202,-2094,-2094,-2094,-2094,-1691,-1691,-1691,-1691,-1691,-1674,-1774,-1774,-2019,-2019,-2019,-2019,-2019,-1988,-1988,-1988,-1988,-1988,-1888,-1888,-1888,-1888,-1888,-1888,-1888,-1488,-2051,-2051,-2051,-2051,-2315,-2315,-2315)
v=1:49
When I try to plot these, my grid does not match the tick marks. Is there a way to fix this in base?
plot(y,x,type='l',col='blue',log='y')
grid(NA,NULL)
Resulting plot:
And the other plot:
plot(v,w,type='l',yaxt='n')
grid(NA,NULL)
axis(2,pretty(w),format(pretty(w)/1000,big.mark=','))
Result:
I put both up because I am using different techniques to label the y axis, and one is a log chart while the other is not. By the way, I have hundreds of other data sets that are placing the grid lines by the tick marks. It is just these two that are not matching grids to ticks.
For the first plot, just use equilogs=F.
For the second plot, since you are using non-default axis ticks, I think you'll have to resort to abline like it says in ?grid. Good luck!

Resources