R: How to draw a level plot with log tick scales - r

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.

Related

Plot curved line on R plot using a condition given two vectors

Given the following empty plot:
plot(1, type="n", xlab="x1", ylab="x2", xlim=c(0, 10), ylim=c(0, 10), axes = F)
axis(1, seq(0,10,1), pos = 0)
axis(2, seq(0,10,1), pos = 0)
lines(x = c(0,10), y = c(10,10))
lines(x = c(10,10), y = c(0,10))
I would like to plot a smooth curve in which x1*x2 = 38, assuming x1 and x2 are both between 0 and 10.
What kind of function could I use to accomplish this?
You may try
plot(1, type="n", xlab="x1", ylab="x2", xlim=c(0, 10), ylim=c(0, 10), axes = F)
axis(1, seq(0,10,1), pos = 0)
axis(2, seq(0,10,1), pos = 0)
lines(x = c(0,10), y = c(10,10))
lines(x = c(10,10), y = c(0,10))
t <- seq(from = 3.8, to = 10, by = .1)
lines(x = t, y = 38/t)
Using curve.
curve(38/x, xlim=c(0, 10), ylim=c(0, 10), xlab='x1', ylab='x2')

Creating stratified histogram using an R function

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)

plot with only horizontal gridlines and labels

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

Legend filled.contour plot

I am trying to create a contour plot with filled.contour and I would like to change the size of the legend title and labels as well as the size of the legend itself. I have already the code for my data which is very similar to the volcano example (easier to replicate).
data(volcano)
filled.contour(volcano, color = terrain.colors, asp = 1)# simple
x <- 10*1:nrow(volcano)
y <- 10*1:ncol(volcano)
filled.contour(x, y, volcano, color = terrain.colors,
plot.title = title(main = "The Topography of Maunga Whau",
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),asp=1))# maybe also asp=1
I have tried to add cex and pch parameters but it seems not work.
key.title = title(main="Height\n(meters)",cex=0.5,pch = 1)
Suggestions would be greatly appreciated.
Thank you.
Use par(cex.main) inside plot.title and key.title:
filled.contour(x, y, volcano, color = terrain.colors,
plot.title = {par(cex.main=1);title(main = "The Topography of Maunga Whau",
xlab = "Meters North", ylab = "Meters West")},
plot.axes = { axis(1, seq(100, 800, by = 100))
axis(2, seq(100, 600, by = 100)) },
key.title = {par(cex.main=0.3);title(main="Height\n(meters)")},
key.axes = axis(4, seq(90, 190, by = 10),asp=1))# maybe also asp=1

How to remove inside border for a stratified histogram without using package

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"))

Resources