I am somewhat new to R and have limited experience with plotting in general. I have been able to work get my data as a time series object in R using zoo, but I am having a hard time having the xaxis be labeled correctly, if it all.
When I plot my zoo object
plot(z)
The x-axis only shows one label, the year 2010. when the series is weekly spanning from April 2009 to October 2010.
I tried to convert my series back to a ts object, and even a data frame (only one column and doesn't include the dates).
Simply, how can I control the x-axis labels generally, and with time series objects?
Thanks in advance!
Start with an example:
x.Date <- as.Date(paste(rep(2003:2004, each = 12), rep(1:12, 2), 1, sep = "-"))
x <- zoo(rnorm(24), x.Date)
plot(x)
If we want different tick locations, we can suppress the default axis plotting and add our own:
plot(x, xaxt = "n")
axis(1, at = time(x), labels = FALSE)
Or combine them:
plot(x)
axis(1, at = time(x), labels = FALSE)
You need to specify the locations for the ticks, so if you wanted monthly, weekly, etc values (instead of observations times above), you will need to create the relevant locations (dates) yourself:
## weekly ticks
plot(x)
times <- time(x)
ticks <- seq(times[1], times[length(times)], by = "weeks")
axis(1, at = ticks, labels = FALSE, tcl = -0.3)
See ?axis.Date for more details, plus ?plot.zoo has plenty of examples of this sort of thing.
The axis labeling doesn't line up with even monthly divsions but may be useful in some situations. Random data (summed) over last 500 days:
xx.Date <- as.Date((Sys.Date()-500):Sys.Date())
x <- zoo(cumsum(rnorm(501)), xx.Date)
tt=time(x)
plot(x, xaxt ="n")
tt <- time(x)
ix <- seq(1, length(tt), by=60) #every 60 days
fmt <- "%b-%d" # format for axis labels
labs <- format(tt[ix], fmt)
axis(side = 1, at = tt[ix], labels = labs, cex.axis = 0.7)
plot.zoo uses the axis functions in R's classic graphics but zoo also offers lattice graphics as well via xyplot.zoo. Just changing plot to xyplot may be sufficient for your needs:
library(zoo)
library(lattice)
# create test data
z <- zooreg(1:83, start = as.Date("2009-04-01"), deltat = 7)
xyplot(z)
Note that there are further examples in ?plot.zoo and ?xyplot.zoo as well as the three vignettes that come with zoo. In those places you can also find find examples of a different approach showing how to use the axis function of classic graphics together with plot.zoo for highly customized axes.
I have captured all the above and a couple of extra options in one place, for my own reference:
# Time series plots with good X axis labels
library(zoo)
# data
today = Sys.Date()
dates = as.Date((today-500):today)
z = zoo (100+cumsum(rnorm(501)), dates)
# method1 : default X axis labels do not look good
?plot.zoo
plot(z)
?plot.ts
plot(ts(z))
# method 2 : Lattice
library(lattice)
?xyplot.zoo
xyplot(z)
xyplot(z, lwd=2, col="tomato")
# method 3 : XTS
library(xts)
?plot.xts
plot(as.xts(z))
plot(as.xts(z), auto.grid=F, major.format="%b %y", las=2)
# method 4 : Base graph
timeline = time(z)
summary(timeline)
index = seq(from=1, to=length(timeline), 90) # put ticks every 90 days
plot(z, xaxt="n")
axis(side=1, at=timeline[index], label=format(timeline[index], "%b %y"), cex.axis=0.8)
# method 5 : ggplot
library(ggplot2)
library(scales)
?date_breaks
df = data.frame(date=as.POSIXct(time(z)), value=as.numeric(z))
head(df)
# default plot
ggplot(df, aes(x=date, y=value)) + geom_line()
# formatted
ggplot(df, aes(x=date, y=value)) + geom_line() +
scale_x_datetime(labels=date_format("%b '%y"))
# custom breaks
ggplot(df, aes(x=date, y=value)) + geom_line() +
scale_x_datetime(labels=date_format("%b '%y"), breaks=date_breaks("3 months"))
if the time is in Date format, this might be helpful.
ggplot(data_frame, aes(date,column)) + geom_point() +
ggtitle("my title")+
scale_x_date(date_breaks = "1 month",date_labels = "%b") + xlab("month") +
ylab("y_axis title")
Related
I can control the 3 y-axis labels, but I'd like to control each of the 3 y-axis ranges as well. Is this possible? I've tried 'ylim', but it only seems to accept a single range.
Also, I'd like to turn the y-axis tick numbers horizontal, if possible, so they don't overlap on each other.
Thanks for any input!
library(zoo)
set.seed(42)
dat <- data.frame(date=seq.Date(as.Date("2020-12-01"), as.Date("2020-12-31"), "day"),
x=runif(31,0,5000),
y=runif(31,0,100),
z=runif(31,0,20))
rownames(dat) <- dat[,1]
dat <- dat[,-1]
plot(as.zoo(dat), ylab=c("label1","label2","label3"))
plot(as.zoo(dat), ylab=c("label1","label2","label3"), ylim=c(c(0,6000),c(0,150),c(0,50)))
click here to see example
There are several problems here:
note that this is dispatching plot.zoo from the generic plot
as.zoo should be read.zoo and the index in zoo objects are NOT row names. See ?zoo and the vignettes that come with zoo vignette(package = "zoo") for more information about zoo objects or find them linked on the zoo CRAN page. See ?read.zoo and vignette("zoo-read", package = "zoo") for more information on read.zoo in particular.
in general it will be easier to deal with the code if you do NOT overwrite variables. Below we have used z to represent the zoo object rather than destroying the original dat.
to get multiple ylim sets they must be passed as a list of pairs. The code in the question is passing a simple vector of 6 values. See ?plot.zoo for more information.
add las=1. See ?par for more information.
Corrected, we have
library(zoo)
set.seed(42)
dat <- data.frame(date = seq.Date(as.Date("2020-12-01"), as.Date("2020-12-31"), "day"),
x = runif(31, 0, 5000),
y = runif(31, 0, 100),
z = runif(31, 0, 20))
z <- read.zoo(dat)
ylab <- c("label1", "label2", "label3")
ylim <- list(c(0, 6000), c(0, 150), c(0, 50))
plot(z, ylab = ylab, ylim = ylim, las = 1)
giving:
You might wanna plot the three data individually, and then use the package patchwork to assemble them :
plot1 <- plot(...)
plot2 <- plot(...)
plot3 <- plot(...)
plot1 + plot2 + plot3 + patchwork::plot_layout(nrow = ..., ncol = ...)
And so, you can arrange the ylim for each of your plots :
plot1 <- plot(..., ylim = c(0,6000))
plot2 <- plot(..., ylim = c(0,150))
plot3 <- plot(..., ylim = c(0,50))
i want to change the format of the x-axis of a plot in R from 1 e+06 to 1 Mio.
What is the right comand to do that?
Thank you for your help.
Jonas
Assuming you work with a base R scatter plot and further assuming you mean what you say, namely that you want labels like "1 Mio" (instead of the number 1000000) on the x-axis, this could work for you:
DATA:
x <- seq(1000000, 10000000, 1000000)
y <- 1:10
SOLUTION:
plot(x,y, xaxt = "n")
axis(1, at = x, labels = paste(1:10, "Mio", sep = " "), las = 2)
This solution avoids printing the default x-axis labels by setting xaxt = "n"and by defining a customized x-axis including the desired axis labels
I want to plot a time series, excluding in the plot a stretch of time in the middle. If I plot the series alone, with only an index on the x-axis, that is what I get. The interior set of excluded points do not appear.
x <- rnorm(50)
Dates <- seq(as.Date("2008-1-1"), by = "day", length.out = length(x))
dummy <- c(rep(1, 25), rep(0, 10), rep(1, length(x) - 35))
plot(x[dummy == 1])
Once the dates are on the x-axis, however, R dutifully presents an accurate true time scale, including the excluded dates. This produces a blank region on the plot.
plot(Dates[dummy == 1], x[dummy == 1])
How can I get dates on the x-axis, but not show the blank region of the excluded dates?
Three alternatives:
1. ggplot2 Apparently, ggplot2 would not allow for a discontinuous axis but you could use facet_wrap to get a similar effect.
# get the data
x = rnorm(50)
df <- data.frame( x = x,
Dates = seq(as.Date("2008-1-1"), by = "day", length.out = length(x)) ,
dummy = c(rep(1, 25), rep(0, 10), rep(1, length(x) - 35)))
df$f <- ifelse(df$Dates <= "2008-01-25", c("A"), c("B"))
# plot
ggplot( subset(df, dummy==1)) +
geom_point(aes(x= Dates, y=x)) +
facet_wrap(~f , scales = "free_x")
2. base R
plot(df$x ~ df$Dates, col= ifelse( df$f=="A", "blue", "red"), data=subset(df, dummy==1))
3. plotrix Another alternative would be to use gap.plot{plotrix}. The code would be something like this one below. However, I couldn't figure out how to make a break in an axis with date values. Perhaps this would and additional question.
library(plotrix)
gap.plot(Dates[dummy == 1], x[dummy == 1], gap=c(24,35), gap.axis="x")
I think I figured it out. Along the lines I proposed above, I had to fiddle with the axis command for a long time to get it to put the date labels in the right place. Here's what I used:
plot(x[dummy == 1], xaxt = "n", xlab = "") # plot with no x-axis title or tick labels
Dates1_index <- seq(1,length(Dates1), by = 5) # set the tick positions
axis(1, at = Dates1_index, labels = format(Dates1[Dates1_index], "%b %d"), las = 2)
Having succeeded, I now agree with #alistaire that it looks pretty misleading. Maybe if I put a vertical dashed line at the break...
I am trying for the last few hours to get the ticks of desired dates with labels as Month-Year on the x-axis of a time series plot. I have tried tons of things available on Stack and others but none worked out so far.
Below is an example of what I am trying so far. I am getting plot with x-axis as a numeric such as 2014.0, while I want it to be in the date format such as Jan-2014.
I am also trying to learn, in case of numeric year labels, how can I start my x-axis with 2014.1 instead of 2014.0 as the first month of my series is January. To get this I tried time function with offset=1 but it didn't work either. Please check below example
## dataframe and its time series
temp_df<- data.frame(date_temp= as.Date(dates_of_data), opp_temp= rnorm(29,mean = 100,sd=5))
temp_ts<- ts(temp_df[,2], start=2014, freq=12)
## plot
plot(temp_ts, axes=F, lwd=3, ylim=c(min(temp_ts),max(temp_ts)), xlab="", ylab="",type="l",col="black", main="")
points(temp_ts,pch=20,col="yellow")
## y-axis
axis(2, ylim=c(min(temp_ts),max(temp_ts)),col="black",lwd=2,line=1)
mtext(2,text="Y-axis count",line=3,col="black")
## x-axis
axis(1,pretty(range(time(temp_ts)),12))
mtext("Time - Year",side=1,col="black",line=2, lwd=3)
## axis(1,pretty(range(time(temp_ts, offset=1)),12)) -- didnt work either
temp_dates<- as.Date(as.yearmon(time(temp_ts)))
axis(side=1, at=tt, labels = FALSE)
axis(side = 1, at = tt[ix], labels = labs[ix], tcl = -0.7, cex.axis = 1)
grid (NULL,NULL, lty = 6, col = "blue")
dev.off()
Couple of things that I have tried so far includes
# 1. par(xaxt="n") ## didn't work
# 2. axis(1, at=seq(from = min(temp_dates),to = max(temp_dates), by="month"), labels=format(temp_dates,"%Y-%b"),las=2)
Can you please tell me how to get x-axis labels as Jan-2014 (Month-Year)?
These are some of the link I went through as requested: here
here
here
here
and
here
EDIT: Below solution works perfectly using zoo library. However I have't been using zoo the whole time in my study and was interested more in doing the other way. Please correct what is wrong in the previous approach.
require(zoo)
dev.off()
x<- (zoo(temp_df$opp_temp, temp_df$date_temp))
plot(x, xaxt = "n")
x_times <- time(x)
ticks <- seq(x_times[1], x_times[length(x_times)], by = "month")
grid (5,5, lty = 6, col = "blue")
axis(1, at = ticks, labels = format(x_times,"%Y-%b"),las=2, tcl = -0.3)
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')
))