When drawing axis for time series, we usually create the tick marks and add the axis separately.
Since I have to plot many time series, I tried to write the following function :
Simple plot command
set.seed(1)
x <- as.ts(rnorm(1:150))
plot <- plot(x, xaxt = "n", yaxt = "n")
Convert a set of commands from this answer into a function
tt = seq(as.Date("1994-03-01"), by="months", length=150)
tsAxis <- function (tt) {
ix <- seq_along(tt) # number of ticks
fmt <- "%b-%y" # format of time
labs <- format(tt, fmt) # names or labels of dates
axis(1, at = tt[ix], labels = labs[ix],
tcl = -0.7, cex.axis = 0.7, las = 2)
}
Then tsAxis(tt) must draw the axis but it doesnot and there is no error either.
Even typing the commands separately does not plot the axis.
Any solutions?
It seems that R represents the x-axis with integers in this case (i.e. x=1 is the first event, x=2 is the second event, etc.). You can see this if you run the code:
set.seed(1)
x <- as.ts(rnorm(1:150))
# Take a look at the x-axis
plot <- plot(x)
We can modify your code to reflect this:
tt = seq(as.Date("1994-03-01"), by="months", length=150)
tsAxis <- function (tt) {
ix <- seq_along(tt) # number of ticks
fmt <- "%b-%y" # format of time
labs <- format(tt, fmt) # names or labels of dates
# Change "at=tt[ix]" to "at=ix" here!
axis(1, at = ix, labels = labs[ix],
tcl = -0.7, cex.axis = 0.7, las = 2)
}
Or if you want to plot every third tick mark, just change ix <- seq_along(tt) to ix <- seq(1, length(tt), 3) and it should work.
Related
I have generated this plot in R with some strange numbers format in the x-axis:
enter image description here
I want to have in the x-axis the numbers in the format (ax) as 2^6, 6^6, 10^6. this would simplify the x-axis to get data in all points. Please do you have any suggestions?
Here my code :
data=read.csv("my_file.csv",row.names = 1)
plot(genes~Prot,cex=1.5,data, function(x) 10^x, xlab="Proteome
size(codons)",ylim=c(0,30), ylab="Genes in pathway")
abline(lm(prot~genes,data),lty=2, lwd=3,col="black")
Use xaxt = 'n' as an argument to plot to turn off the x-axis labelling. Then use the Axis function to set tick marks and label as required.
# Generating some data
power <- seq(1, 6, length.out = 20)
Prot = 10^power
genes <- runif(20, min = 5, max = 30)
# plotting
plot(x= Prot, y= genes, cex=1.5, xlab="Proteome size(codons)", ylab="Genes in pathway", xaxt = 'n', log = 'xy')
Axis(at = c(2^6, 6^6, 10^6), side = 1, labels = c('2^6', '6^6', '10^6'), las = 1)
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 have some wind speed and direction data over a course of some time and I need to plot it into a feather plot.
After surfing the web for some time, I find a function someone wrote to plot the feather plot that works for me (Thank you if you are reading this!!). My problem now is that I don't know how to manipulate the labelling of the x-axis.
After the plotting, the figure looks like this:
Now the x-axis doesn't look too bad here, but imagine I have 200 data points (and thus ticks) instead of 10, and the axis ticks can get a bit confusing. So I was hoping someone can help me manipulate the x-axis, specifically messing with the ticks.
The code to plot the figure is:
stg <- scan(what="", sep="\n")
9/20/15_12:00 2.597058824 157.9411765
9/21/15_0:00 2.177192982 185.1754386
9/21/15_12:00 2.577391304 189.2173913
9/22/15_0:00 1.984955752 237.4336283
9/22/15_12:00 3.993859649 252.6315789
9/23/15_0:00 1.613392857 175.5357143
9/23/15_12:00 3.849166667 216.8333333
9/24/15_0:00 2.138135593 117.0338983
9/24/15_12:00 3.32605042 216.302521
9/25/15_0:00 1.490178571 239.8214286
df <- read.table(textConnection(stg), sep="")
colnames(df) <- c("Time", "wsp", "wdir")
df$PTime <- as.POSIXct(df$Time, format="%m/%d/%y_%H:%M")
feather.plot2 <- function (r, theta, xpos, yref = 0, use.arrows = TRUE, col.refline = "lightgray",
fp.type = "s", main = "", xlab = "", ylab = "", xlabels = NULL,
...)
{
if (missing(xpos))
xpos <- 1:length(theta)
if (fp.type == "m")
theta <- 5 * pi/2 - theta
x <- r * cos(theta)
y <- r * sin(theta)
xmult <- diff(range(xpos))/(diff(range(y)) * 2)
x <- x * xmult
xlim <- range(c(xpos, x + xpos))
ylim <- range(c(y, yref))
oldpin <- par("pin")
xdiff <- xlim[2] - xlim[1]
ydiff <- ylim[2] - ylim[1]
plot(0, xlim = xlim, ylim = ylim, type = "n", main = main,
xlab = xlab, ylab = ylab, axes = TRUE, xaxt = "n")
box()
if (is.null(xlabels))
axis(1)
else axis(1, at = xpos, labels = xlabels)
abline(h = yref, col = col.refline)
if (use.arrows)
arrows(xpos, yref, xpos + x, y, length = 0.1, ...)
else segments(xpos, yref, xpos + x, y, ...)
par(pin = oldpin)
}
feather.plot2(df$wsp, df$wdir, fp.type="m", xlabels=df$PTime)
And what I want is something like having big ticks for 12:00, and smaller ticks for 0:00, like in this figure:
Although I don't know why the label for this figure comes out as "Sun - Thu" instead of dates...
The code for this figure is:
daterange=c(min(df$PTime), max(df$PTime))
plot(x=df$PTime, y=df$wsp, xaxt="n", type="l")
axis.POSIXct(1, at=seq(daterange[1], daterange[2], by="day"))
axis.POSIXct(1, at=seq(daterange[1], daterange[2], by="12 hours"), tcl = -0.3, labels=FALSE )
I've tried using using these axis commands on the feather plot, but it did not work. So I'd appreciate any help/advice. Thank you so much!!
I'm seeing two requests: Major and minor ticks; and More compact axis annotation of date-times. Step 1: Suppress the default axis creation. Step 2: The usual manor is to label the major ticks, so we would determine the proper location of those ticks and give a format specification to the labels. Step 3: place the minor tick marks. Most of this you've already figured out, and I would have thought the format problem was the easiest one to solve, so let's see:
plot(x=df$PTime, y=df$wsp, xaxt="n", type="l")
axis.POSIXct(1, at=seq(daterange[1], daterange[2], by="day"), format="%m-%d %H%P",
lwd.ticks=2)
axis.POSIXct(1, at=seq(daterange[1], daterange[2], by="12 hours"),
tcl = -0.3, labels=FALSE )
Seems to succeed at what I think are your goals. The use of by = "day" may be what leads the interpreter to choose the three letter abbrev of day names. (I don't really know.)
I am very new to R and have made a filled.contour plot using interpolated data like the data found in Plotting contours on an irregular grid . Using some sample data from Plotting contours on an irregular grid , I made a filled.contour and simple scatterplot using the following codes
x <- datr$Lat
y <- datr$Lon
z <- datr$Rain
require(akima)
fld <- interp(x,y,z)
filled.contour(fld)
plot(x,y)
Is there a way to make the plot(x,y) and filled.contour(fld) on the same plot (overlaying)? I have tried the points(x,y), but this doesn't match the x and y axes. In Matlab, I believe I would do this with hold, but I am unsure how to do it on R.
Thanks!
You could use the arguments plot.title or plot.axes for that:
x <- 10*1:nrow(volcano)
y <- 10*1:ncol(volcano)
filled.contour(x, y, volcano, plot.title = {
points(x = 200, y = 200)
})
(via)
One way is to read the code for filled.contour, and do a
little hacking like so:
Make your figure:
filled.contour(fld)
Define these constants by copying them from the arguments list.
nlevels = 20
zlim = range(z, finite = TRUE)
las = 1
levels = pretty(zlim, nlevels)
xlim = range(x, finite = TRUE)
ylim = range(y, finite = TRUE)
xaxs = "i"
yaxs = "i"
asp = NA
Calculate these values by copying code from the function body
mar.orig <- (par.orig <- par(c("mar", "las", "mfrow")))$mar
w <- (3 + mar.orig[2L]) * par("csi") * 2.54
Set the layout by copying code from the function body
layout(matrix(c(2, 1), ncol = 2L), widths = c(1, lcm(w)))
Noteice that the figure is actually plotted after the color scale,
but we don't wnat to reverse the order of the layout because layout
actually sets the 'current' region as the last region because the
first call to plot.new will cause the current region to wrap around
to the first region. Hence, when you set the plot window and plot the points via:
plot.window(ylim=ylim,xlim=xlim)
points(x,y)
title(main='title',
sub='Sub-Title',
xlab='This is the x axis',
ylab='This is the y axis')
They overlay figure as desired.
I have a plot that has $-amounts and dates on y and x axis respectively. Currently the dollar amounts range from $0-15 million. Something like this:
x <- rnorm(20)^2 * 1000000
plot(x)
R does stuff like '1.0e+07' instead of '10,000,000' and also orients the text vertically instead of horizontally.
My questions are:
1) how would I get the scale text to be horizontally oriented?
2) how would I get R to use 10MM instead of '10,000,000' or '1.0e+07'?
1) See the scipen option in ?options which is a penalty against the use of scientific notation. For better control, you need to plot the axis by hand with labels you want.
2) See las in ?par which controls to orientation crudely of axis labels.
For 1):
x <- rnorm(20)^2 * 10000000
layout(matrix(1:2, ncol = 2))
plot(x)
getOption("scipen")
opt <- options("scipen" = 20)
getOption("scipen")
plot(x)
options(opt)
layout(1)
which gives
To plot your own axis try
plot(x / 10000000, axes = FALSE)
axis(1)
pts <- pretty(x / 10000000)
axis(2, at = pts, labels = paste(pts, "MM", sep = ""))
box()
Which gives
Where we use pretty() to select pretty locations for the ticks just as R would and then add a custom axis. Notice how we suppress axis drawing in the plot() call and then add back the axes and the plot frame with calls to axis() and box().
For 2) combining with 1)
opt <- options("scipen" = 20)
op <- par(mar = c(5,7,4,2) + 0.1) ## extra margin to accommodate tick labs
x <- rnorm(20)^2 * 10000000
plot(x, las = 1, ylab = "") ## no y-axis label
title(ylab = "label", line = 5.5) ## need to plot the axis label
par(op)
options(opt)
Which gives
Notice how we use las in the plot() call, and we need to create some extra margin space to accommodate the tick labels. We also need to plot the label by hand otherwise R will stick it in amongst the tick labels.
For the custom axis labels, add the las = 1 to the axis() call:
op <- par(mar = c(5,5,4,2) + 0.1)
plot(x / 10000000, axes = FALSE, ylab = "")
axis(1)
pts <- pretty(x / 10000000)
axis(2, at = pts, labels = paste(pts, "MM", sep = ""), las = 1)
title(ylab = "my label", line = 4)
box()
par(op)
Which produces
Use axis with custom labels. First, divide your data by 1 million. And then create a series with the MM notation using paste()
y <-rnorm(20)^2 * 1000000 /1000000
x <-11:30
plot(x,y, yaxt="n")
my.axis <-paste(axTicks(2),"MM",sep="")
axis(2,at=axTicks(2), labels=my.axis)
The text is now horizontal. But if you run into a problem use, las=1 to force labels to be horizontal.
axis(2,at=axTicks(2), labels=my.axis, las=1)