Related
By default, the cartesian axes in R are on the bottom and left side of a plot.
How do I center the axes, as shown in the picture below?
Example
## using; data; generated; by; bgoldst;;
## estimate curve
x <- seq(-1,1.5,0.1);
y <- c(1.3,1.32,1.33,1.32,1.25,1.1,0.7,0.5,0.4,0.38,0.4,0.41,0.42,0.43,0.44,0.4,0.3,0.1,0,-0.05,-0.1,-0.15,-0.2,-0.24,-0.28,-0.3);
f <- splinefun(x,y);
## calculate precise points along estimated curve
x <- seq(-1,1.5,0.01);
y <- f(x);
plot(x, y, type = 'l')
#ForrestRStevens was too quick for me, I was too busy trying to estimate your curve using a spline :)
## estimate curve
x <- seq(-1,1.5,0.1);
y <- c(1.3,1.32,1.33,1.32,1.25,1.1,0.7,0.5,0.4,0.38,0.4,0.41,0.42,0.43,0.44,0.4,0.3,0.1,0,-0.05,-0.1,-0.15,-0.2,-0.24,-0.28,-0.3);
f <- splinefun(x,y);
## calculate precise points along estimated curve
x <- seq(-1,1.5,0.01);
y <- f(x);
## precompute limits
xlim <- c(min(x),max(x));
ylim <- c(min(y)-0.4,max(y)+0.2);
## set global plot params
par(xaxs='i',yaxs='i',mar=c(1,1,3,3)+0.1); ## "internal" axis spacing, meaning no extended range, and slightly adjust margins
## draw plot
plot(NA,xlim=xlim,ylim=ylim,axes=F,ann=F); ## set plot bounds, no default ornaments
arrows(c(0,xlim[1]),c(ylim[1],0),c(0,xlim[2]),c(ylim[2],0),0.05); ## draw custom axes
mtext('y',3,1,at=0,las=1,cex=0.8,family='serif'); ## y label
mtext('x',4,1,at=0,las=1,cex=0.8,family='serif'); ## x label
lines(x,y,col='#aaaacc'); ## draw line on top
In general, you can draw pretty much anything with base graphics, but it's often more involved than if you used more sophisticated packages, because you have to draw everything by hand.
I think something like the following does what you'd like in base graphics:
## Simulate your data:
x <- seq(-3, 3, by=0.01)
y <- 0.5*x - 0.3*x^2 + 0.4*x^3
## Plot the polynomial function, removing axis ticks and bounding box,
## as well as the axis labels:
plot(x, y,
type="l",
xaxt='n', yaxt='n',
bty='n',
xlab='', ylab='',
col="blue")
## Next add in your axis arrows:
arrows(min(x), 0, max(x), 0, lwd=1, length=0.15)
arrows(0, min(y), 0, max(y), lwd=1, length=0.15)
## And plot your x/y labels. Note that if you want them
## actually at the end of the arrows you would need to
## remove the pos= argument and shorten your arrows by
## a small amount. To match your original figure, you can
## alter the x/y coordinate to be the max() instead.
text(0, min(y), "y", pos=2)
text(min(x), 0, "x", pos=3)
I am trying to generate a bar plot with a categorical X axis and two different y axis. I am trying to use twoord.plot to generate the bar plot as follows:
x <- c("A","B","C","D","E")
ry <- c(0.1,0.2,0.3,0.4,0.5)
ly <- c(0.15,0.25,0.35,0.45,0.55)
library(plotrix)
twoord.plot(x,ry,x,ly,
xlab="xLabel",
ylab="yLabel",
rylab="ryLabel",
main="Main",
type=c("bar","l"),lcol=rainbow(length(x)),rcol=4)
However, I am getting an error "Error in plot.window(...) : invalid 'xlim' value".
Is there a way to work with categorical/character variables as x-axis? Also, is there a way to rotate the X-axis labels so that they show up at 45 degrees?
I have been able to get this code to work with the following changes:
xNumeric <- seq(1:length(x))
twoord.plot(xNumeric,ly,xNumeric,ry,
xlab="xLabel",
ylab="yLabel",
rylab="ryLabel",
main="Main",
type=c("bar","o"),lcol=rainbow(length(x)),rcol = 4,xticklab = x)
However, I still need to figure out how to rotate the X-axis labels as well as adding a legend to differentiate between which is the box plot and which is the line plot. Any help on this would be appreciated
Thank you.
This isn't in plotrix, but...
ry <- c(0.1,0.2,0.3,0.4,0.5)
ly <- c(15,35,65,75,80)
x <- 1:5
xlabs <- c("A","B","C","D","E")
barplot(ly, xaxt="n", yaxt="n", xlab="xLabel", ylab="lyLabel", ylim=c(0,100))
axis(2, seq(0,100,by=5), seq(0,100,by=5), las=2) # you can adjust positions of ly labels
par(new=TRUE)
plot(ry~x, xaxt="n", yaxt="n", xlab="", ylab="", ylim=c(0,1))
axis(1, 1:5, xlabs)
axis(4, 1:10/10, 1:10/10, las=2) # you can adjust positions of ry labels
mtext("ryLabel", 4, line=2)
And you would obviously need to edit a bit to get the colors, etc. that you seem to be going for.
the type argument to xyplot() can take "s" for "steps." From help(plot):
The two step types differ in their x-y preference: Going from
(x1,y1) to (x2,y2) with x1 < x2, 'type = "s"' moves first
horizontal, then vertical, whereas 'type = "S"' moves the other
way around.
i.e. if you use type="s", the horizontal part of the step has its left end attached to the data point, while type="S" has its right end attached to the data point.
library(lattice)
set.seed(12345)
num.points <- 10
my.df <- data.frame(x=sort(sample(1:100, num.points)),
y=sample(1:40, num.points, replace=TRUE))
xyplot(y~x, data=my.df, type=c("p","s"), col="blue", main='type="s"')
xyplot(y~x, data=my.df, type=c("p","S"), col="red", main='type="S"')
How could one achieve a "step" plot, where the vertical motion happens between data points points, i.e. at x1 + (x2-x1)/2, so that the horizontal part of the step is centered on the data point?
Edited to include some example code. better late than never I suppose.
I am using excellent #nico answer to give its lattice version. Even I am ok with #Dwin because the question don't supply a reproducible example, but customizing lattice panel is sometimes challenging.
The idea is to use panel.segments which is the equivalent of segments of base graphics.
library(lattice)
xyplot(y~x,
panel =function(...){
ll <- list(...)
x <- ll$x
y <- ll$y
x.start <- x - (c(0, diff(x)/2))
x.end <- x + (c(diff(x)/2, 0))
panel.segments(x.start, y, x.end, y, col="orange", lwd=2)
panel.segments(x.end[-length(x.end)], y[1:(length(y)-1)],
x.end[-length(x.end)], y[-1], col="orange", lwd=2)
## this is optional just to compare with type s
panel.xyplot(...,type='s')
## and type S
panel.xyplot(...,type='S')
})
This is a base graphics solution, as I am not too much of an expert in lattice.
Essentially you can use segments to draw first the horizontal, then the vertical steps, passing the shifted coordinates as a vector.
Here is an example:
set.seed(12345)
# Generate some data
num.points <- 10
x <- sort(sample(1:100, num.points))
y <- sample(1:40, num.points, replace=T)
# Plot the data with style = "s" and "S"
par(mfrow=c(1,3))
plot(x, y, "s", col="red", lwd=2, las=1,
main="Style: 's'", xlim=c(0, 100))
points(x, y, pch=19, col="red", cex=0.8)
plot(x, y, "S", col="blue", lwd=2, las=1,
main="Style: 'S'", xlim=c(0, 100))
points(x, y, pch=19, col="blue", cex=0.8)
# Now plot our points
plot(x, y, pch=19, col="orange", cex=0.8, las=1,
main="Centered steps", xlim=c(0, 100))
# Calculate the starting and ending points of the
# horizontal segments, by shifting the x coordinates
# by half the difference with the next point
# Note we leave the first and last point as starting and
# ending points
x.start <- x - (c(0, diff(x)/2))
x.end <- x + (c(diff(x)/2, 0))
# Now draw the horizontal segments
segments(x.start, y, x.end, y, col="orange", lwd=2)
# and the vertical ones (no need to draw the last one)
segments(x.end[-length(x.end)], y[1:(length(y)-1)],
x.end[-length(x.end)], y[-1], col="orange", lwd=2)
Here is the result:
I am trying to control how many z labels should be written in my contour plot plotted with contourplot() from the lattice library.
I have 30 contour lines but I only want the first 5 to be labelled. I tried a bunch of things like
contourplot(z ~ z+y, data=d3, cuts=30, font=3, xlab="x axis", ylab="y axis", scales=list(at=seq(2,10,by=2)))
contourplot(z ~ z+y, data=d3, cuts=30, font=3, xlab="x axis", ylab="y axis", at=seq(2,10,by=2))
but nothing works.
Also, is it possible to plot two contourplot() on the same graph? I tried
contourplot(z ~ z+y, data=d3, cuts=30)
par(new=T)
contourplot(z ~ z+y, data=d3, cuts=20)
but it's not working.
Thanks!
Here is my take:
library(lattice)
x <- rep(seq(-1.5,1.5,length=50),50)
y <- rep(seq(-1.5,1.5,length=50),rep(50,50))
z <- exp(-(x^2+y^2+x*y))
# here is default plot
lp1 <- contourplot(z~x*y)
# here is an enhanced one
my.panel <- function(at, labels, ...) {
# draw odd and even contour lines with or without labels
panel.contourplot(..., at=at[seq(1, length(at), 2)], col="blue", lty=2)
panel.contourplot(..., at=at[seq(2, length(at), 2)], col="red",
labels=as.character(at[seq(2, length(at), 2)]))
}
lp2 <- contourplot(z~x*y, panel=my.panel, at=seq(0.2, 0.8, by=0.2))
lp3 <- update(lp2, at=seq(0.2,0.8,by=0.1))
lp4 <- update(lp3, lwd=2, label.style="align")
library(gridExtra)
grid.arrange(lp1, lp2, lp3, lp4)
You can adapt the custom panel function to best suit your needs (e.g. other scale for leveling the z-axis, color, etc.).
You can specify the labels as a character vector argument and set the last values with rep("", 5), so perhaps for the example you offered on an earlier question about contour
x = seq(0, 10, by = 0.5)
y = seq(0, 10, by = 0.5)
z <- outer(x, y)
d3 <- expand.grid(x=x,y=y); d3$z <- as.vector(z)
contourplot(z~x+y, data=d3)
# labeled '5'-'90'
contourplot(z~x+y, data=d3,
at=seq(5,90, by=5),
labels=c(seq(5,25, by=5),rep("", 16) ),
main="Labels only at the first 5 contour lines")
# contourplot seems to ignore 'extra' labels
# c() will coerce the 'numeric' elements to 'character' if any others are 'character'
?contourplot # and follow the link in the info about labels to ?panel.levelplot
I was just wondering if there is a way to get rid of axis values, either the x-axis or y-axis respectively, in an r-plot graph.
I know that axes = false will get rid of the entire axis, but I would only like to get rid of the numbering.
Remove numbering on x-axis or y-axis:
plot(1:10, xaxt='n')
plot(1:10, yaxt='n')
If you want to remove the labels as well:
plot(1:10, xaxt='n', ann=FALSE)
plot(1:10, yaxt='n', ann=FALSE)
Using base graphics, the standard way to do this is to use axes=FALSE, then create your own axes using Axis (or axis). For example,
x <- 1:20
y <- runif(20)
plot(x, y, axes=FALSE, frame.plot=TRUE)
Axis(side=1, labels=FALSE)
Axis(side=2, labels=FALSE)
The lattice equivalent is
library(lattice)
xyplot(y ~ x, scales=list(alternating=0))
#Richie Cotton has a pretty good answer above. I can only add that this page provides some examples. Try the following:
x <- 1:20
y <- runif(20)
plot(x,y,xaxt = "n")
axis(side = 1, at = x, labels = FALSE, tck = -0.01)
you can also put labels inside plot:
plot(spline(sub$day, sub$counts), type ='l', labels = FALSE)
you'll get a warning. i think this is because labels is actually a parameter that's being passed down to a subroutine that plot runs (axes?). the warning will pop up because it wasn't directly a parameter of the plot function.
Change the axis_colour to match the background and if you are modifying the background dynamically you will need to update the axis_colour simultaneously.
* The shared picture shows the graph/plot example using mock data ()
### Main Plotting Function ###
plotXY <- function(time, value){
### Plot Style Settings ###
### default bg is white, set it the same as the axis-colour
background <- "white"
### default col.axis is black, set it the same as the background to match
axis_colour <- "white"
plot_title <- "Graph it!"
xlabel <- "Time"
ylabel <- "Value"
label_colour <- "black"
label_scale <- 2
axis_scale <- 2
symbol_scale <- 2
title_scale <- 2
subtitle_scale <- 2
# point style 16 is a black dot
point <- 16
# p - points, l - line, b - both
plot_type <- "b"
plot(time, value, main=plot_title, cex=symbol_scale, cex.lab=label_scale, cex.axis=axis_scale, cex.main=title_scale, cex.sub=subtitle_scale, xlab=xlabel, ylab=ylabel, col.lab=label_colour, col.axis=axis_colour, bg=background, pch=point, type=plot_type)
}
plotXY(time, value)