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)
Related
I am trying to create this stratified histogram on R, however I am not getting the right plot. I would like to use the rect function as well if possible.
How would I write an R function to create this stratified histogram using the iris dataset in R?
This is the code so far:
strathist = function(x, y, ylab = "Frequency", xlab = "", main = ""){
cols = hcl(h=seq(0, 360, by = 120))
h = hist(x, breaks = 24, plot = FALSE)
tb = table(y, cut(x, h$breaks))
plot.new()
barplot(tb, ylim = c(0, max(h$count)), col = cols,
ylab = ylab, xlab = xlab, main = main, axisnames = FALSE)
box()
axis(1, 0:(length(h$breaks)-1), h$breaks)
axis(2)
legend("topright", c(rownames(tb)), fill = cols)
}
with(iris, strathist(Sepal.Width, Species, xlab = "Sepal.Width", main = "Stratified Histogram"))
There are a few different ways to do this, if you insist on using R base, you could use two barplots, one to add the colors and one to add the boxes:
strathist = function(x,
y,
ylab = "Frequency",
xlab = "",
main = "") {
cols = hcl(h = seq(0, 360, by = 120))
h = hist(x,
breaks = 24,
plot = F)
tb = table(y, cut(x, h$breaks))
ylim <- c(-.05 * max(colSums(tb)),
1.25 * max(colSums(tb)))
barplot(
tb,
col = cols,
ylim = ylim,
ylab = ylab,
xlab = xlab,
main = main,
axisnames = FALSE,
border = NA,
space = 0
)
barplot(
colSums(tb),
ylim = ylim,
col = NA,
ylab = ylab,
xlab = xlab,
main = main,
axisnames = FALSE,
add = T,
space = 0
)
box()
axis(1, seq(0,
length(h$breaks) - 1,
by = 5),
seq(min(x),max(x), by = .5))
axis(2)
legend("topright", c(rownames(tb)), fill = cols,border = NA,)
}
with(
iris,
strathist(Sepal.Width, Species, xlab = "Sepal.Width", main = "Stratified Histogram")
)
Or you could go the somewhat easier route to use ggplot2:
library(ggplot2)
ggplot(iris,aes(x = Sepal.Width)) +
geom_histogram(bins = 25,aes(fill = Species)) +
geom_histogram(bins = 25, fill = NA, color = 'black') +
theme_minimal()
Created on 2020-09-13 by the reprex package (v0.3.0)
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
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 would like to draw a level plot with x and y scales as a log10 ticks.
For example, I have a normal level plot like this.
x <- 10*1:nrow(volcano)
y <- 10*1:ncol(volcano)
filled.contour(x, y, volcano, color = terrain.colors, plot.title = title(main = "Volcano topolgy", xlab = "Meters North", ylab = "Meters West"), plot.axes = { axis(1, seq(100, 800, by = 100)); axis(2, seq(100, 600, by = 100)) }, key.title = title(main = "Height\n(meters)"), key.axes = axis(4, seq(90, 190, by = 10)))
But, the x and y scales are not log tick scales. I found the other library "latticeExtra" with log tick scale function. For example, using the same x and y from above I can draw the log ticks, but cannot fill the contour data.
library(lattice)
library(latticeExtra)
xyplot(y ~ x, scales = list(x = list(log = 10), y = list(log = 10)), xscale.components = xscale.components.log10ticks, yscale.components = yscale.components.log10ticks)
How can I draw a level plot with log tick scales? I would like to plot scatters on the level plot later on as a log location.
Thanks in advance.
Here's an alternative using lattice and latticeExtra
library(lattice)
library(latticeExtra)
xx <- 1:nrow(volcano)
yy <- 1:ncol(volcano)
levelplot(
x = volcano,
xlim = range(xx),
ylim = range(yy),
scales = list(x = list(log = 10), y = list(log = 10)),
xscale.components = xscale.components.log10ticks,
yscale.components = yscale.components.log10ticks
)
if you want to keep using filled.contour you can logtransform the x and y data directly and adjust the axes accordingly with a custom axis statement, but it's not very elegant (the base::plot log = "xy" parameter sadly doesn't do anything in filled.contour):
x <- log(10*1:nrow(volcano))
y <- log(10*1:ncol(volcano))
filled.contour(x, y, volcano, color = terrain.colors,
plot.title = title(main = "Volcano topolgy",
xlab = "Meters North",
ylab = "Meters West"),
plot.axes = { axis(1, at = log(seq(100, 800, by = 100)), labels = seq(100, 800, by = 100));
axis(2, at = log(seq(100, 600, by = 100)), labels = seq(100, 600, by = 100)) },
key.title = title(main = "Height\n(meters)"),
key.axes = axis(4, seq(90, 190, by = 10)))
you can also try if ggplot2 with scale_y_log10() and scale_x_log10() would work for you, see this question and answer.
I'm plotting data with colored error bars in R. I'd like to show "sample error bars" (with the colour used in the plot) in the legend, but how?
library("Hmisc")
d1=data.frame(x=c(1,2,3,4,5), meanY=c(1,2,3,4,5), sdY=c(1,1,1,1,1))
d2=data.frame(x=c(1,2,3,4,5), meanY=c(2.1,3.3,4.1,5.2,6.1), sdY=c(1.3,1.2,1.4,1.1,1.2))
plot(1, 1, type="n", xlab="X values", ylab="Y values", xlim=c(1,5), ylim=c(0,7))
with ( data = d1, expr = Hmisc::errbar(x, meanY, meanY+sdY, meanY-sdY, pch=1, cex=.5, cap=.0025, add=T, errbar.col="red") )
with ( data = d2, expr = Hmisc::errbar(x, meanY, meanY+sdY, meanY-sdY, pch=1, cex=.5, cap=.0025, add=T, errbar.col="green") )
legend(x="bottomright", legend=c("d1", "d2"), pch=1, pt.cex=.5)
Somewhat manual build of legend...
# bind data together to simplify plot code
df <- rbind(d1, d2)
# plot
with(df,
errbar(x = x + c(rep(0.05, nrow(d1)), rep(-0.05, nrow(d2)), # dodge points to avoid overplotting
y = meanY,
yplus = meanY + sdY,
yminus = meanY - sdY,
pch = 1, cex = 0.5, cap = .0025,
errbar.col = rep(c("red", "green"), times = c(nrow(d1), nrow(d2))),
xlab = "X values", ylab = "Y values",
xlim = c(1, 5), ylim = c(0, 7)))
# create data for legend
df_legend <- data.frame(x <- c(4.5, 4.5),
y <- c(1, 2),
sdy <- c(0.3, 0.3))
# add symbols to legend
with(df_legend,
errbar(x = x,
y = y,
yplus = y + sdy,
yminus = y - sdy,
pch = 1, cex =.5, cap = .0025,
errbar.col = c("red", "green"),
add = TRUE))
# add text to legend
with(df_legend,
text(x = x + 0.2,
y = y,
labels = c("d2", "d1")))
# add box
with(df_legend,
rect(xleft = x - 0.2,
ybottom = y[1] - 0.5,
xright = x + 0.4,
ytop = y[2] + 0.5))