I have some barplot
barplot(1:3, axes=FALSE)
to which I would like to add horizontal gridlines with labels using base R.
I get the first part using
par(xpd = TRUE, mai=c(0.5,1,0.5,0.2)) # to extend lines to the left of plotting area
barplot(1:3, axes=FALSE) # plotting area
grid(nx=0, ny=3, col="gray") # horizontal grid lines
barplot(1:3, axes=FALSE, add=TRUE) # get grid lines into background
but I fail to get the labels on the left end. That is, at the left end of the gridlines, I would like to have the Y-values, here 1 and 2.
The documentation of ?grid gives a solution to this problem. From section Note.
Note
If more fine tuning is required, use abline(h = ., v = .) directly.
old_par <- par(xpd = TRUE, mai=c(0.5,1,0.5,0.2))
barplot(1:3, axes = FALSE)
abline(h = 1:3, col = "grey", lty = "dotted")
barplot(1:3, axes = FALSE, add = TRUE)
text(x = -0.5, y = 1:3, labels = 1:3)
par(old_par)
To have the y axis labels at the end of the grid lines and to place them automatically, a function can be defined.
segmText <- function(x0, x1, y, ...){
segments(x0 = x0, x1 = x1,
y0 = y, y1 = y, ...)
text(x = x0, y = y, labels = y)
}
old_par <- par(xpd = TRUE, mai = c(0.5,1,0.5,0.2)) # to extend lines to the left of plotting area
barplot(1:3, axes = FALSE)
segmText(x0 = -0.5, x1 = 4, y = 1:3, col = "grey", lty = "dotted")
barplot(1:3, axes = FALSE, add = TRUE)
par(old_par)
Edit
A simpler solution seems to be in the comment by user d.b
graphics.off()
barplot(1:3, axes = FALSE, col = NA, border = NA)
abline(h = 1:3, col = "grey", lty = "dotted")
barplot(1:3, axes = FALSE, add = TRUE)
axis(2, at = 1:3, labels = 1:3, las = 2, col = NA)
You could use lines() within a sapply() and use mtext(). Plot an empty plot beforehand.
plot(x=0:4, y=0:4, type="n", axes=FALSE, xlab="", ylab="")
sapply(1:3, function(x) lines(0:4, rep(x, 5), lty=3, col="gray"))
barplot(1:3, axes=FALSE, add=TRUE)
mtext(1:3, side=2, line=0, at=1:3, las=1, adj=0)
You can trim this by changing e.g. line=-1 or play around with adj.
Produces
Related
I am trying to use two different Y axis with the same X Axis and when I set both axes to false the Year wont show up
library(lubridate)
x <- dataset$Date
y <- dataset$AvgCostPerKwh
z <- dataset$ActualkWhSold
par(mar=c(5, 4, 4, 6) + 0.1)
plot(year(x),y, pch = 16, axes = FALSE, ylim = c(0.030,0.090), xlab = "", ylab = "",
type = "b", col="black", main = "Wholesale Power cost")
axis(2, ylim =(range(c(y))), col = "black", las =1)
mtext("$ per KWh", side = 2, line = 2.5)
box()
par(new = TRUE)
plot(year(x),z, pch = 15, xlab = "", ylab = "",ylim=c(5000000,45000000),
axes = FALSE, type="b", col="red")
mtext("Kwh's Sold", side=4, col="red", line=4)
axis(4, ylim=(range(c(z))), col = "red", las=1)
mtext("Year", side = 1, col="black",line=2.5)
legend("topleft", legend = c("AvgCostPerKwh", "ActualKwhSold"),
text.col = c("black", "red"),
pch=c(15,15),col=c("black", "red"))
Image 1
When I set one of the plots to true, I get overlapping values one one side, but the year on the bottom shows up.
library(lubridate)
x <- dataset$Date
y <- dataset$AvgCostPerKwh
z <- dataset$ActualkWhSold
par(mar=c(5, 4, 4, 6) + 0.1)
plot(year(x),y, pch = 16, axes = TRUE, ylim = c(0.030,0.090), xlab = "", ylab = "",
type = "b", col="black", main = "Wholesale Power cost")
axis(2, ylim =(range(c(y))), col = "black", las =1)
mtext("$ per KWh", side = 2, line = 2.5)
box()
par(new = TRUE)
plot(year(x),z, pch = 15, xlab = "", ylab = "",ylim=c(5000000,45000000),
axes = FALSE, type="b", col="red")
mtext("Kwh's Sold", side=4, col="red", line=4)
axis(4, ylim=(range(c(z))), col = "red", las=1)
mtext("Year", side = 1, col="black",line=2.5)
legend("topleft", legend = c("AvgCostPerKwh", "ActualKwhSold"),
text.col = c("black", "red"),
pch=c(15,15),col=c("black", "red"))
image 2
I am not sure, I have followed other examples on here about 2 Y axis and I can't get mine to work.
I have answered my own question for anyone interested, I forgot to add
year(as.Date(dataset$Date, format = "%m/%d/%Y"),"%Y")
at the top before adding
plot(year(x), y, pch=16, axes=FALSE, ylim=c(0.030,1), xlab="", ylab="",
type="b",col="black", main="Wholesale Power Cost")
I'm plotting two xyplots with a doubleYScale plot. I would like to hide the top x-axis, but everything I tried so far either does nothing or hides all axes. Is this even possible?
library(lattice)
library(latticeExtra)
x<-seq(1:10)
y<-x^2
y2<-x*2
plot1<-xyplot(y~x, col="black", type="l", ylab="Label1", xlab="")
plot2<-xyplot(y2~x, col="red", type="l", ylab="Label2", xlab="", scales=list(y=list(col="red")))
doubleYScale(plot1, plot2, add.axis=TRUE, add.ylab2 = TRUE, scales=list(x=list(draw=FALSE)))
update(trellis.last.object(),
par.settings = simpleTheme(col = c("black", "red"), lty=c(1,1)), horizontal=F, scales=list(x=list(draw=T)))
As you can see from the proposed solution below, lattice isn't really set up to easily do this particular thing. That said, it's pretty fully customizable, and with some work you can get what you're after. Here, with just a few inline comments, is code that will fully suppress that top axis:
library(lattice)
library(latticeExtra)
library(grid)
## Sample data
x <- seq(1:10)
y <- x^2
y2 <- x*2
## Prepare list of scales setting that suppresses ticks on top axis
myScales <- list(x = list(tck = c(1,0)))
## Prepare parameter settings, including setting the color used in
## plotting axis line to "transparent"
myTheme <- simpleTheme(col = c("black", "red"),
lty = c(1,1))
myTheme <- c(myTheme, list(axis.line = list(col = "transparent")))
## Write a custom axis function that only plots axis lines on the
## left, right, and bottom sides
myAxisFun <- function(side, line.col, ...) {
if (side == "left") {
grid.lines(x = c(0, 0), y = c(0, 1),
default.units = "npc")
} else if (side == "right") {
grid.lines(x = c(1, 1), y = c(0, 1),
default.units = "npc")
} else if (side == "bottom") {
grid.lines(x = c(0, 1), y = c(0, 0),
default.units = "npc")
}
axis.default(side = side, line.col = "black", ...)
}
## Construct two component plots
plot1 <- xyplot(y ~ x, col="black", type = "l",
ylab = "Label1", xlab = "",
par.settings = myTheme,
scales = myScales,
axis = myAxisFun)
plot2 <- xyplot(y2 ~ x, col="red", type = "l",
ylab = "Label2", xlab = "",
par.settings = myTheme,
scales = myScales,
axis = myAxisFun)
## Meld the two plots
doubleYScale(plot1, plot2, add.ylab2 = TRUE)
i am writing up a function to generate a stratified histogram.
Here is my code.
i would like to remove the inside border (so those stack counts are separated by colour only, not colour and border). any ideas?
data("iris")
strathist = function(x, y, ylab = "Frequency", xlab = "", main = ""){
cols = hcl(h=seq(0, 300, by = 50), fixup = FALSE)
h = hist(x, breaks = 20, plot = F)
tb = table(y, cut(x, h$breaks))
par(mar = rep(4, 4))
plot.new()
barplot(tb, space = 0, ylim = c(-0.4, 2 + max(h$count)), col = cols,
ylab = ylab, xlab = xlab, main = main, axisnames = F)
axis(1, 0:(length(h$breaks)-1), h$breaks)
box()
legend("topright", c(rownames(tb)), cex = 0.8, fill = cols)
}
with(iris, strathist(Sepal.Length, Species, xlab = "Sepal.Length", main = "Stratified Histogram of Iris Species"))
I'm plotting a cdf of some data, and I've added logarithmic scale on the "x" axis.
The ticks spacing is exactly as I want it to be, but I'd like to be able to add
some tick marks on specific points.
I don't want to change the distribution of the ticks in my plot, from n by n to m by m, I want simply to have, among the ticks from n by n, some further tick marks on some values.
I'd like to have it reflected in both x and y axis, so that I can fit a grid into these new marks throughout the graph.
So far I have the graph, and the grid -- I don't mind about having the grid behind or upon the graph, I just want to add some custom ticks.
# Cumulative Distribuition
pdf("g1_3.pdf")
plot(x = f$V2, y = cumsum(f$V1), log = "x", pch = 3,
xlab = "Frequency", ylab = "P(X <= x)",
panel.first = grid(equilogs = FALSE))
axis(1, at = c(40, 150))
abline(h = 0.6, v = 40, col = "lightgray", lty = 3)
abline(h = 0.6, v = 150, col = "lightgray", lty = 3)
dev.off()
UPDATE: The graph I have so far:
Considering the initial script, and the tips given by #BenBolker, I had to use:
axis(side = 1, at = c([all the ticks you want]))
in order to add the ticks in the graph. Here's the final result:
# Cumulative Distribuition
pdf("g1_3.pdf")
plot(x = f$V2, y = cumsum(f$V1), log = "x", pch = 3,
xlab = "Frequency", ylab = "P(X <= x)", axes = FALSE)
ticks = c(1, 5, 10, 40, 150, 500, 1000)
axis(side = 1, at = ticks)
axis(side = 2)
abline(h = seq(0, 1, 0.2), v = ticks, col = "lightgray", lty = 3)
box()
When I draw grid lines on a plot using abline() the grid lines are drawn over the data.
Is there a way to draw the abline() lines behind the data? I feel this would look better.
Example:
x <- seq(0, 10)
y <- x
plot(x, y, col = 'red', type = 'o', lwd = 3, pch = 15)
abline(h = seq(0, 10, .5), col = 'lightgray', lty = 3)
abline(v = seq(0, 10, .5), col = 'lightgray', lty = 3)
The plot produced has the gray grid lines going over the data (red line). I would like the red line to be on top of the gray lines.
The panel.first argument of plot() can take a list or vector of functions so you can put your abline() calls in there.
plot(1:4, panel.first =
c(abline(h = 1:4, lty = 2, col = 'grey')
,abline(v = 1:4, lty = 2, col = 'grey')))
Use plot() to set up the plotting window, but use type = "n" to not plot any data. Then do your abline() calls, or use grid(), and then plot the data using whatever low-level function is appropriate (here points() is fine).
x <- seq(0, 10)
y <- x
plot(x, y, type = "n")
abline(h = seq(0, 10, .5), col = 'lightgray', lty = 3)
abline(v = seq(0, 10, .5), col = 'lightgray', lty = 3)
points(x, y, col = 'red', type = 'o', lwd = 3, pch = 15)
or
## using `grid()`
plot(x, y, type = "n")
grid()
points(x, y, col = 'red', type = 'o', lwd = 3, pch = 15)
See ?grid for details of how to specify the grid as per your abline() version.
Plot first with type="n" to establish coordinates. Then put in the grid lines, then plot again with your regular plot type:
plot(x, y, col = 'red', type = 'n', lwd = 3, pch = 15)
abline(h = seq(0, 10, .5), col = 'lightgray', lty = 3)
abline(v = seq(0, 10, .5), col = 'lightgray', lty = 3)
par(new=TRUE)
plot(x, y, col = 'red', type = 'o', lwd = 3, pch = 15)
I admit that I have always thought the name for that par parameter was "backwards."
Another way of creating grid lines is to set tck=1 when plotting or in the axis function (you may still want to plot the points using points after creating the grid lines.