I have a data frame with the first column named "Date." It has values like "2016-01-01, 2016-01-02 ..." etc. The second column is named "precipBulk," and it just has decimal values (ex. 3.36, 1.57, etc.). The third column is named "abundance," and it also has decimal values. I want to graph both "abundance" and "precipBulk" on one graph(Like the image), but I want the x-axis to have intervals with every month instead of every other month like it is now. I know there's a way to do it in ggplot2 using "scale_x_date()" but I can't graph both of the y values in one graph with ggplot2 for some reason. Is there a way to do it without using ggplot2? if not, any tips on how I would graph dual y-axis to achieve this with ggplot2?
Graph link https://i.stack.imgur.com/SZXgT.png `
Small portion of data frame https://i.stack.imgur.com/PvTED.png
To make the graph, I did:
x = frame$Date
y1 = frame$precipBulk
y2 = frame$abundance
plot(x,y1, type = "l",ylab="Bulk Precipitation",xlab="Month",col="blue", main = "Precipitation vs Mosquito Abundance (OSBS 2016)", cex.main = 1)
par(new = TRUE)
plot(x, y2, type = "l",yaxt="n",xaxt="n",ylab="",col="red")
axis(side = 4)
legend('topleft', c("Precipitation", "Mosquito Abundance"), col= c("blue", "Red"),lty=c(1,1), adj = c(0,0.6), cex= 0.75)
You need to turn the x-axis off (as you did) and then add it manually, perhaps reducing the size if necessary so that the axis tick labels fit, otherwise, R will decide for you.
x <- seq(as.Date("2017-01-01"), as.Date("2018-01-01"), "day")
plot(x, rnorm(length(x)), xaxt="n")
at <- seq(min(x), max(x), "month")
axis(side=1, at=at, labels=format(at, "%b"), cex.axis=0.7)
I've been producing different sets of charts, all in R base. I have a problem though with barplots. I've formatted the x-axis to show the dates by year, however, many years show up several times. I would like each year to only show up once.
Here's my example code:
library(quantmod)
start <- as.Date("01/01/2010", "%d/%m/%Y")
#Download FRED data
tickers <- c("WTISPLC", "DCOILBRENTEU")
fred <- lapply(tickers, function(sym) {na.omit(getSymbols(sym, src="FRED", auto.assign=FALSE, return.class = "zoo"))})
df <- do.call(merge, fred)
#Subset for start date
df <- subset(df, index(df)>=start)
#Create bar plot
par(mar = c(5,5,5,5))
barplot(df[,2], names.arg=format(index(df), "%Y"), ann=FALSE, bty="n", tck=-0, col=1:1, border=NA, space=0); title(main="Example chart", ylab="y-axis")
This example should be reproducible and show clearly what I mean. Now, I've been researching how to add a separate x-axis and how to define that axis. So, I've tried to add the following code:
#Plot bars but without x-axis
barplot(df[,2], names.arg=format(index(df), "%Y"), ann=FALSE, bty="n", tck=-0, xaxt="n", col=1:1, border=NA, space=0); title(main="Example chart", ylab="y-axis")
# Set x-axis parameters
x_min <- min(index(df))
x_max <- max(index(df))
xf="%Y"
#Add x-axis
axis.Date(1, at=seq(as.Date(x_min), x_max, "years"), format=xf, las=1, tck=-0)
This does not give me an error message, but it also does absolutely nothing in terms of drawing an x-axis.
Please do not provide a solution for ggplot. Even though I like ggplot, these barplots are part of a bigger project for me, all using R base and I would not like to introduce ggplot into this project now.
Thanks!
If you are not limited to barplot, you may use the following very simple solution using plot.zoo behind the screens:
# only use what you want, and avoid multiple plots
df2 <- df[ , 2]
# use zoo.plot's functionality
plot(df2, main = "Example Chart", ylab = "y-axis", xlab = "")
This yields the following plot:
I know it is not a barplot, but I don't see what a barplot would add here. Please let me know, whether this is what you want or not.
Edit 1
If you do want to use barplot you may use the following code:
### get index of ts in year format
index_y <- format(index(df), "%Y")
### logical vector with true if it is the start of a new year
index_u <- !duplicated(index_y)
### index of start of new year for tick marks
at_tick <- which(index_u)
### label of start of new year
labels <- index_y[index_u]
### draw barplot without X-axis, and store in bp
### bp (bar midpoints) is used to set the ticks right with the axis function
bp <- barplot(df[,2], xaxt = "n", ylab= "y-axis")
axis(side = 1, at = bp[at_tick] , labels = labels)
yielding the following plot:
Please let me know, whether this is what you want.
Edit 2
We need to take into account two bits of information, when explaining why the ticks and labels group together at the left-hand side.
(1) in barplot, space defines the amount of space before each bar (as a fraction of the average bar width). In our case, it defaults to around zero (see ?barplot for details). In the illustration below, we use spaces of 0.0, 0.5, and 2.0
(2) Barplot returns a numeric vector with the midpoints of the bars drawn (again see the help pages for more detailed info). We can use these midpoints to add information to the graph, like we do in the following excerpt: after storing the result of barplot in bp, we use bp to set the ticks: axis(... at = bp[at_tick] ... ).
When we add space, the location of the bar midpoints change. So, when we want to use the bar midpoints after adding space, we need to be sure we have the right information. Simply stated, use the vector returned by barplot with the call where you added space. If you don't, the graph will be messed up. In the below, if you continue to use the bar-midpoints of the call with (space=0), and you increase space, the ticks and labels will group at the left-hand side.
Below, I illustrate this with your data limited to 3 months in 2017.
In the top layer 3 barplots are drawn with space equal to 0.0, 0.5 and 2.0. The information used to calculated the location of ticks and labels is recalculated and saved at every plot.
In the bottom layer, the same 3 barplots are drawn, but the information used to draw the ticks and labels is only created with the first plot (space=0.0)
# Subset for NEW start for illustration of space and bp
start2 <- as.Date("01/10/2017", "%d/%m/%Y")
df2 <- subset(df, index(df)>=start2)
### get index of ts in month format, define ticks and labels
index_y2 <- format(index(df2), "%m")
at_tick2 <- which(!duplicated(index_y2))
labels2 <- index_y2[!duplicated(index_y2)]
par(mfrow = c(2,3))
bp2 <- barplot(df2[,2], xaxt = "n", ylab= "y-axis", space= 0.0, main ="Space = 0.0")
axis(side = 1, at = bp2[at_tick2] , labels = labels2)
bp2 <- barplot(df2[,2], xaxt = "n", ylab= "y-axis", space= 0.5, main ="Space = 0.5")
axis(side = 1, at = bp2[at_tick2] , labels = labels2)
bp2 <- barplot(df2[,2], xaxt = "n", ylab= "y-axis", space= 2.0, main ="Space = 2.0")
axis(side = 1, at = bp2[at_tick2] , labels = labels2)
### the lower layer
bp2 <- barplot(df2[,2], xaxt = "n", ylab= "y-axis", space= 0.0, main ="Space = 0.0")
axis(side = 1, at = bp2[at_tick2] , labels = labels2)
barplot(df2[,2], xaxt = "n", ylab= "y-axis", space= 0.5, main ="Space = 0.5")
axis(side = 1, at = bp2[at_tick2] , labels = labels2)
barplot(df2[,2], xaxt = "n", ylab= "y-axis", space= 2.0, main ="Space = 2.0")
axis(side = 1, at = bp2[at_tick2] , labels = labels2)
par(mfrow = c(1,1))
Have a look here:
Top layer: bp recalculated every time
Bottom layer: bp space=0 reused
Cutting and pasting the commands in your console may illustrate the effects better than the pic above.
I hope this helps.
You could use the axis function, I used match to obtain the indices of the dates on the axis:
space=1
#Plot bars but without x-axis
barplot(df[,2], names.arg=format(index(df), "%Y"), ann=FALSE, bty="n", tck=-0, xaxt="n",
col=1:1, border=NA, space=space); title(main="Example chart", ylab="y-axis")
# Set x-axis parameters
x_min <- min(index(df))
x_max <- max(index(df))
#Add x-axis
axis(1, at=match(seq(as.Date(x_min), x_max, "years"),index(df))*(1+space),
labels = format(seq(as.Date(x_min), x_max, "years"),"%Y"),lwd=0)
Hope this helps!
This time I am struggling to adjust the X axis in a two-screen zoo plot.
Here's an example, inspired from a previous post:
x.Date <- as.Date(paste(rep(2003:2004, each = 12), rep(1:12, 2), 1, sep = "-"))
x <- zoo(data.frame(rnorm(24), rnorm(24)), x.Date)
then when I plot without X axis and add an axis separately
plot(x, xaxt = "n")
axis(1, at = time(x), labels = FALSE)
nothing happens (also with more complex versions of the axis, for example with labels)...
What am I doing wrong?
Many thanks
Benoit
One idea is to use xyplot.zoo the lattice version of plot.zoo. Very easy to customize your x-axis using scales parameter.
library(lattice)
xyplot(x,
scales=list(
x=list( at=time(x),
format='%y-%m')
))
Here is the code generating a plot of an xts object:
require("quantmod")
getSymbols("SPY")
plot(Cl(SPY))
Which yields the following plot:
Can you remove the y-axis values (the prices) from a plot of an xts object?
Hint: passing yaxt='n' doesn't work.
Removing the y-axis is easy, but it also removes the x-axis. A couple options:
1) Easy -- use plot.zoo:
plot.zoo(Cl(SPY), yaxt="n", ylab="")
2) Harder-ish -- take pieces from plot.xts:
plot(Cl(SPY), axes=FALSE)
axis(1, at=xy.coords(.index(SPY), SPY[, 1])$x[axTicksByTime(SPY)],
label=names(axTicksByTime(SPY)), mgp = c(3, 2, 0))
3) Customize-ish -- modify plot.xts so axes= accepts a vector of axes to plot and/or TRUE/FALSE.
Adding to Joshua's answer, to modify plot.xts(), all you need to do is alter the following section:
if (axes) {
if (minor.ticks)
axis(1, at = xycoords$x, labels = FALSE, col = "#BBBBBB")
axis(1, at = xycoords$x[ep], labels = names(ep), las = 1,lwd = 1, mgp = c(3, 2, 0))
#This is the line to change:
if (plotYaxis) axis(2)
}
and obviously you add the parameter plotYaxis=TRUE to the function definition.
You can also try specifying that the x and y as labels are empty, or contain no values/characters. Try using the term xlab="" in your plot command:
e.g. plot(beers,ranking,xlab="",ylab="")
By not including anything between the quotation marks, R doesn't plot anything.
Using this command, you can also specific the labels, so to make the label for the x axis
'beer', use the term xlab="beer".
I have a question regarding the command plot().
Is there a way to fully eliminate the x-axis and replace it with own values? I know that I can get rid of the axis by doing
plot(x,y, xaxt = 'n')
and then add an axis with
axis(side = 1 etc.)
However, when I add the axis, obviously it still refers to the data plotted as 'x'.
I would only like to plot the 'y'-values and add the x-axis my own in the sense of just "drawing" the x-axis with own values specified. Is there any way to do that?
The background of this question is that my two data frames differ in their length and therefore I cannot plot them.
Not sure if it's what you mean, but you can do this:
plot(1:10, xaxt = "n", xlab='Some Letters')
axis(1, at=1:10, labels=letters[1:10])
which then gives you the graph:
You could set labels = FALSE inside axis(...) and then print the labels in a separate command using text(...). This option would allow you to rotate the text in case you need it.
lablist<-as.vector(c(1:10))
axis(1, at=seq(1, 10, by=1), labels = FALSE)
text(seq(1, 10, by=1), par("usr")[3] - 0.2, labels = lablist, srt = 45, pos = 1, xpd = TRUE)
Detailed explanation here