R: Make plot axis as in histogram - r

I want the y axis in regular plot() function to start at the bottom of the plot area similar to hist() function. In other words I would like to have zeros of both axis at the same level. Here is my working example
set.seed(1)
data <- data.frame(
type = as.factor(sample(c('A', 'B', 'C'), size = 100, replace = T)),
value = rexp(100, 1/3)
)
plot(data$type)
par(new=TRUE)
plot(tapply(data$value, data$type, mean),
xaxt="n", yaxt="n", xlab="", ylab="",
xlim=c(0.55,3.45), ylim=c(0, 5), bty='n', pch=24, bg='black')
axis(4)
I tried to use parameter yaxs = 'i' in the plot() function, but it moved the axis too low. Is there any solution to this?

Find one variant
set ylim in first plot
try
plot(data$type, yaxs = 'i',ylim=c(0,max(apply(data, 2, table)[[1]])))
par(new=TRUE)
plot(tapply(data$value, data$type, mean),
xaxt="n", yaxt="n", xlab="", ylab="",
xlim=c(0.55,3.45), ylim=c(0, 5), bty='n', pch=24, bg='black',yaxs = 'i')
axis(4)
axis(1,at=c(0,5)) #only for show that one lvl

Related

Plotting multiple plots - rescaling of axes

I found, that axes were rescaled during multiple plotting using par(new=T) parameter.
An example to demonstrate this:
a <- seq(1,10, by = 0.25)
b <- sin(a)
c <- sin(2*a)+1
d <- sin(0.5*a)+2
df <- data.frame(a,b,c,d)
plot(df$a, df$b, type="l")
par(new=T)
plot(df$a, df$c, type="l", col="blue")
par(new=T)
plot(df$a, df$d, type="l", col="red")
This is the result.
Instead of real scales, I have a transformed curves.
And this is the real result:
I used parameters axes=F, xlab="", ylab="" and did not see this "rescaling".
I find it very dangerous, that it is so easy to transform the data during plotting if you do not control y-limits.
Are there better ways to control y-limits than looking for min and max values in all plotted data to avoid this "rescaling" effect?
I have several quite big files and each of them gives only one line from 10 in one plot and I have several plots on one page to compare my data.
The code for the last "correct" image:
plot(df$a, df$b, type="l", ylim=c(-1.5,3.5))
par(new=T)
plot(df$a, df$c, type="l", ylim=c(-1.5,3.5), col="blue", axes=F, xlab="", ylab="")
par(new=T)
plot(df$a, df$d, type="l", ylim=c(-1.5,3.5), col="red", axes=F, xlab="", ylab="")
#Create an empty plot with enough xlim and ylim to accomodate all data
plot(1, 1, xlim = range(df[,1]), ylim = range(df[,-1]), type = "n", ann = FALSE)
#Draw the three lines
lines(df$a, df$b)
lines(df$a, df$c, col="blue")
lines(df$a, df$d, col="red")

Time series double y axis plot with x axis in “year”-“month” in R

I have the following code for a double y axis plot in r. Everything works fine, but I want to change the x axis from every 18 months to every 12 months. I have tried every "axis(side=1, at=....)" I could think of. Any random number between 0:1.5 will work for "Data$Monthly_Gen" and 0:100 for Data$Ave_GenXXXX" for reproducing. Thanks.
Data2 <- ts(Data$Monthly_Gen, start=c(2005,1),end=c(2012,12),frequency=12)
Data2B <- ts(Data$Ave_Gen_MonthSOCO, start=c(2005,1),end=c(2012,12),frequency=12)
Data2C <- ts(Data$Ave_Gen_MonthTVA, start=c(2005,1),end=c(2012,12),frequency=12)
Data2D<-ts(Data$Monthly_Gen_Othersx10,start=c(2005,1),end=c(2012,12),frequency=12)
Data2E <- ts(Data$Monthly_Gen_Othersx9, start=c(2005,1),end=c(2012,12),frequency=12)
par(mar=c(4, 4, 2, 4) + 0.1)
plot(as.xts(Data2), major.format = "%Y-%m",ylab="",las=1,ylim=c(0,2))
lines(as.xts(Data2D), major.format = "%Y-%m", xlab="", ylab="",
type="l", col="black",main="",lty="dotted" ,lwd=2)
lines(as.xts(Data2E), major.format = "%Y-%m", xlab="", ylab="",
type="l", col="black",main="",lty="longdash" ,lwd=2)
mtext("Generation",side=2,line=3)
box()
par(new=TRUE)
plot(as.xts(Data2B), major.format = "%Y-%m", xlab="", ylab="",
axes=FALSE, type="l", col="#E69F00",main="",lwd=2,ylim=c(0,130))
mtext("Monthly Average Lambda",side=4,col="black",line=2.5)
axis(4, col="black",col.axis="black",las=1)
lines(as.xts(Data2C), major.format = "%Y-%m", xlab="", ylab="",
type="l", col="#56B4E9",main="",lwd=2.5)
mtext("Date",side=1,col="black",line=3)
legend("topright",legend=c("Total Generation","X1 Generation","X2 Generation","Area Lambda","X2 Area Lambda"),text.col=c("black","black","black","#E69F00","#56B4E9"),col=c("black","black","black","#E69F00","#56B4E9"),cex=.75,lty=c("solid","longdash","dotted","solid","solid"))`
This is easy to do with zoo. In my opinion, zoo is more powerful than ts.
#Create zoo series
Data2 <- zooreg(runif(96,0,1.5), start = as.yearmon(2005),end = as.yearmon(2012), freq = 12)
Data2B <- zooreg(runif(96,0,100), start = as.yearmon(2005),end = as.yearmon(2012), freq = 12)
#Create 12-month sequence for axis
twelve <-seq(1,length(Data2),12)
plot(Data2,ylab="",las=1,ylim=c(0,2),xaxt = "n")
#add x-axis at 12 months
axis(1,at=index(Data2)[twelve],labels=format(index(Data2)[twelve],"%Y-%m"))
par(new=TRUE)
plot(Data2B,xlab="",ylab="",las=1,ylim=c(0,130),xaxt = "n",yaxt = "n",col="blue")
#add yy axis
axis(4, col="black",col.axis="black",las=1)
Here's a solution using only the base plot() functions. I think what you really want is seq.Date() for something like this
set.seed(123)
nn <- 7*12 # months
x1 <- ts(rnorm(nn),start=c(2005,1),freq=12)
x2 <- ts(rpois(nn,20),start=c(2005,1),freq=12)
tt <- seq.Date(from=as.Date("2005-01-01"),by="month",length.out=nn)
plot(tt, x1, col="blue", type="l", xaxt="n", xlab="", ylab="")
par(new=TRUE)
plot(tt, x2, col="red", type="l", xaxt="n", yaxt="n", xlab="", ylab="")
axis(4)
dates <- seq(from=as.Date("2005-01-01"), to=as.Date("2012-12-01"), by="18 month")
axis(1, at=dates, labels = format(dates, "%Y-%m"))

Combining a box plot with a dot plot using different Y scales

I am trying to generate a figure that consists of a box plot with a set of points overlaid on the boxplot. The key issue is that the y scale of the box plot is different from that of the points. (Yes, this is very poor visualization - but I'm not the lead author of the paper). I have been able to generate a plot with different y scales, but am facing an issue with the x axis.
Using the following code
boxdata <- data.frame(fc=runif(100, min=-4, max=4),
sym=sample(c('A', 'B', 'C', 'D', 'E'), 100, replace=TRUE))
par(mar=c(5, 4, 1, 6) + 0.1)
junk <- boxplot(fc ~ sym, boxdata, las=2, pch=19, ylim=c(-5,5),
varwidth=FALSE, xaxt='n')
mtext("Y-axis",side=2,line=2.5)
axis(1, at=1:5, labels=sort(unique(boxdata$sym)), las=2)
par(new=TRUE)
x <- 1:5
y <- runif(5, min=-1, max=1)
plot(x,y, col='red', type='p', pch=15, axes=FALSE, ylim=c(-1,1), cex=1.5)
axis(4, ylim=c(-1,1), las=1)
I get the following figure. As you can see the points in red do not align with the X-axis labels (or box centers). The box centers are located at 1:5, so I thought that the plot() call with x = 1:5 should line up.
Could anybody point me to a way to line up the second set of points with the box centers?
EDIT: This problem doesn't occur if I plot two sets of points on different y scales
plot(1:10, runif(10) , col='red', pch=19)
par(new=TRUE)
plot(1:10, runif(10, min=5, max=20), col='blue', pch=19, axes=FALSE)
axis(4, las=2)
Don't use par(new=TRUE), but use pointsinstead of the second plotcommand:
boxdata <- data.frame(fc=runif(100, min=-4, max=4),
sym=sample(c('A', 'B', 'C', 'D', 'E'), 100, replace=TRUE))
par(mar=c(5, 4, 1, 6) + 0.1)
junk <- boxplot(fc ~ sym, boxdata, las=2, pch=19, ylim=c(-5,5),
varwidth=FALSE, xaxt='n')
mtext("Y-axis",side=2,line=2.5)
axis(1, at=1:5, labels=sort(unique(boxdata$sym)), las=2)
x <- 1:5
y <- runif(5, min=-1, max=1)
points(x, 4*y, col='red', type='p', pch=15, ylim=c(-1,1), cex=1.5)
axis(4, at=seq(-4, 4, by=2), label=seq(-1, 1, by=.5), las=1)
EDIT: Check the ?bxp help page. You will find a note that xlim defaults to range(at, *) + c(-0.5, 0.5). So, you could specify the same for your second plot:
junk <- boxplot(fc ~ sym, boxdata, las=2, pch=19, ylim=c(-5,5),
varwidth=FALSE, xaxt='n')
mtext("Y-axis",side=2,line=2.5)
axis(1, at=1:5, labels=sort(unique(boxdata$sym)), las=2)
par(new=TRUE)
plot(x,y, col='red', type='p', pch=15, axes=FALSE, ylim=c(-1,1), cex=1.5,
xlim=range(x) + c(-0.5, 0.5))
axis(4, ylim=c(-1,1), las=1)

How to avoid wired ylab error when plotting in R

I need a two y-axes figure. hrbrmstr suggested to use simple plots. But when adapting the graph to my setting I observed I cannot add the ylab on the right hand side, getting a wired error:
Error in axis(4, ylim = c(0, 1), col = "black", col.axis = "black", las = 1, :
'labels' is supplied and not 'at'
Is this avoidable?
look at the code the bottom line fpr SOURCE OF ERROR
featPerf <- data.frame( expS=c("1", "2", "3", "4"),
exp1=c(1000, 0, 0, 0),
exp2=c(1000, 5000, 0, 0),
exp3=c(1000, 5000, 10000, 0),
exp4=c(1000, 5000, 10000,20000),
accuracy=c(0.4, 0.5, 0.65, 0.9) )
# make room for both axes ; adjust as necessary
par(mar=c(5, 5, 5, 7) + 0.2)
# plot the bars first with no annotations and specify limits for y
#barplot(as.matrix(featPerf[,2:5]), axes=FALSE, xlab="", ylab="", ylim=c(0, max(colSums(featPerf[2:5]))))
barplot(as.matrix(featPerf[,2:5]), axes=FALSE, xlab="", ylab="", beside=TRUE)
# make the bounding box (or not...it might not make sense for your plot)
#box()
# now make the left axis
axis(2, ylim=c(0, max(colSums(featPerf[2:5]))), col="black", las=1)
# start a new plot
par(new=TRUE)
# plot the line; adjust lwd as necessary
plot(x=1:4, y=featPerf[,6], xlab="Experiments", ylab="Abs. # of Features", axes=FALSE, type="l", ylim=c(0,1), lwd=5)
# annotate the second axis -- SOURCE OF ERROR -> VVVVVVVVVVVVVVVVVV
axis(4, ylim=c(0,1), col="black", col.axis="black", las=1, labels="Accuracy")
Like this?
par(mar=c(4,4,1,4) + 0.2)
barplot(as.matrix(featPerf[,2:5]), axes=FALSE, xlab="", ylab="", beside=TRUE)
axis(2, ylim=c(0, max(colSums(featPerf[2:5]))), col="black", las=1)
par(new=TRUE)
plot(x=1:4, y=featPerf[,6], xlab="Experiments", ylab="Abs. # of Features", axes=FALSE, type="l", ylim=c(0,1), lwd=5, col="blue")
axis(4, ylim=c(0,1), col="blue", col.axis="blue", las=1)
mtext("Accuracy",4,line=2, col="blue")
For the record, it is never a good idea to stack plots on top of each other this way (with two axes). I've made the line and the axis the same color in an attempt to draw attention to what you are doing, but this is still a very bad idea.
First of all it is not advisable to use two Y-axes in a same plot.
If you add at argument to the axis call, you get the name "Accuracy" on the right hand side of the plot.
axis(4, ylim=c(0,1), col="black", col.axis="black", las=1, labels="Accuracy",
at = .5)

overlaid plots using different axes in R

I am trying to overlay two graphs onto the same axes. I set up my axes limits and labels first, but then when I plot the graphs they resize and are not on my pre-determined scale.
I have pared my code down into a simple example. You can see that 100 and 10 are showing up at the same place on the y axis. Please help!
x<- 1:3
y1<- c(100, 75, 20)
y2<- c(10, 9, 4)
plot.new()
plot(0, type="n",
xlim=c(1,max(x)), ylim=c(0,max(y1,y2)),
xlab= "x label", ylab= "y label", main= "This stupid graph doesn't work!")
par(new=TRUE)
par(new=TRUE)
plot(x,y1, type="b", pch=19, col="orchid",
axes=FALSE, ann=FALSE)
par(new=TRUE)
plot(x,y2, type="b", pch=19, col="slateblue",
axes=FALSE, ann=FALSE)
legend("topright",c("This is","Annoying"), col=c("orchid","slateblue"), pch=19)
You want to use lines to add the second line, meanwhile making sure that ylim allows for all the values being plotted to fit within the plotting region.
plot(y1 ~ x, ylim = range(c(y1, y2)), xlab = "x label", ylab = "y label",
main = "This one might work!", type = 'b', pch = 19, col = "orchid")
lines(y2, type = 'b', pch = 19, col = 'slateblue')
legend("topright", c("R is", "awesome"), col = c("orchid","slateblue"), pch = 19)

Resources