I am trying to get marginal distribution plots in base R (if not possible, non-base R code is okay, but only for doing the rotating).
How do you rotate the y-axis marginal plot (in yellow)?
The code I have to make this plot:
# plot layout
layout_mat <- matrix(c(2, 0,
1, 3),
nrow = 2,
byrow = T)
layout(layout_mat, c(3, 1), c(1, 3))
par(mar = c(3,3,1,1))
# main scatterplot
plot(x = mtcars[order(mtcars$qsec), c("wt", "mpg")],
xlab = "Vehicle Weight (1000 lbs)",
ylab = "Miles Per Gallon (MPG)",
pch = 16,
cex = seq(3.5, 1.25, length.out = nrow(mtcars)),
col = rgb(0, 0, 0, .5),
axes = F,
xlim = c(1, 6),
ylim = c(8, 35))
box(lwd = 1.5)
axis(side = 1, at = 1:6, labels = 1:6, lwd = 0, lwd.ticks = 1)
axis(side = 2, at = seq(10, 35, 5), label = seq(10, 35, 5), lwd = 0, lwd.ticks = 1, las = 1)
dx <- density(mtcars[order(mtcars$qsec), "wt"])
dy <- density(mtcars[order(mtcars$qsec), "mpg"])
# x axis plot
par(mar = c(0,3,1,1))
plot(dx, axes = F, main = "", xlab= "", ylab = "", lwd =2)
# y-axis plot
par(mar = c(3,0,1,1))
plot(dy, axes = F, main = "", xlab= "", ylab = "", lwd =2)
rect(xleft = par("usr")[1],
ybottom = par("usr")[3],
xright = par("usr")[2],
ytop = par("usr")[4],
col = rgb(235, 216, 52, .5*255, maxColorValue = 255))
Thanks to #user20650 for this answer
Passing the y-axis points for y's density to x and the x-axis points for y's density to y will plot it flipped:
plot(dy$y, dy$x, type="l", axes = F, main = "", xlab= "", ylab = "", lwd = 2)
Related
I am trying to make the following graph with R-plot:
I have the following code in R:
x = 0:8
f = log2(x)
plot(x, f, main="Função Logarítmica", xlab="X - Abscissas", ylab="Y - Ordenadas", t='l', ylim=c(-3,3), xlim=c(0,8), col=4, axes=F)
axis(1, pos=0, at=seq(from=0, to=8, by=0.2))
axis(2, pos=0)
# Inclui linhas de grade
abline(h=seq(-3,3,0.5),v=seq(-3,8,0.5),lty=3,col="gray", lwd=2)
The graph generated with the R-plot:
How should I make my R graph look like the figure?
I'm not sure what it is you want to change in the figure, but here's a reasonable replica:
x = seq(0.1, 8, 0.1)
f = log2(x)
plot(x, f, main = "Função Exponencial",
xlab = "X - Abscissas", ylab = "Y - Ordenadas", t = 'n',
ylim= c(-3, 3), xlim = c(0, 8), col = 4, axes = FALSE)
polygon(x = c(0, 8, 8, 0), y = c(-3, -3, 3, 3), col= "#e3e9ff")
abline(h = seq(-3, 3, 0.1), v = seq(-3, 8, 0.1), col = "white", lwd = 2)
lines(x, f, lwd = 2, col = "red3")
axis(1, pos = 0, at = 0:8)
axis(2, pos = 0)
text(label = c("\u215b", "\u00bc", "\u00bd"),
c(0.125, 0.25, 0.5), c(0.2, -0.2, -0.2), cex = 1.3)
for(i in seq(-3, 3)) {
lines(c(0, 2^i, 2^i), c(i, i, 0), lty = 2)
points(2^i, i, pch = 16, cex = 1.5)
}
I have found multiple ways to create a secondary y-axis in plot but I couldn't find a way to create a secondary y-axis in histogram.
Here is a sample code:
a <- sample(90:110, 50, replace=TRUE)
b <- runif(50, min=0, max=1)
hist(a)
lines(b)
b is too small to show in hist(a) so is there any way that I can see both in the histogram?
Technically a solution may be quite an identical to the approach proposed for the plots in this answer. The idea is to use overlapping of two plots as proposed by #r2evans.
It makes sense to use color coding:
# set color rules
col_a <- "red"
col_b <- "darkblue"
col_common <- "black"
Then let's draw the histogram and the plot:
# draw a histogram first
par(mar = c(5, 5, 5, 5) + 0.3)
hist(a, col = col_a, axes = FALSE, xlab = "", ylab = "", main = "")
# add both axes with the labels
axis(side = 1, xlim = seq(along.with = b), col = col_a, col.axis = col_a)
mtext(side = 1, text = "a_value", col = col_a, line = 2.5)
axis(side = 2, col = col_a, col.axis = col_a, ylab = "")
mtext(side = 2, text = "a_Frequency", col = col_a, line = 2.5)
# ... and add an overlaying plot
par(new=TRUE)
plot(b, ylim = c(0, 1), axes = FALSE, col = col_b, type = "l", xlab = "", ylab = "")
points(b, col = col_b, pch = 20, xlab = "", ylab = "")
axis(side = 3, xlim = seq(along.with = b), col = col_b, col.axis = col_b)
mtext(side = 3, text = "b_index", col = col_b, line = 2.5)
axis(side = 4, ylim = c(0, 1), col = col_b, col.axis = col_b)
mtext(side = 4, text = "b_value", col = col_b, line = 2.5)
box(col = col_common)
I am creating a plot where I plot the variable on the X-axis against that on the Y-axis, and I am adding histograms of the variables as well. I have added a trend-line to the plot using abline().
The problem is that it does not appear to respect the xlim = c(0, 20) in the plot region as it extends beyond the limits of the x-axis. I tried playing around with the xpd option, but to no avail. Next I tried fiddling with the different par()options, but found nothing that could help with this issue.
What I want is for the trend-line to be the exact length of the x-axis. Any help is much appreciated. In this particular case the trend-line is almost flat, but the slope will change when I do the same for other variables.
MWE -- NOTE: I am only providing 15 data points to illustrate the issue so the graph will differ from the image provided.
df.data <- data.frame(id = 1:15,
ll = c(-9.53026, -6.50640,-6.50640, -7.68535, -11.80899, -8.42790,
-6.50640, -6.50640, -7.92405, -6.50640, -8.95522, -9.99228,
-10.02286, -8.95969, -6.07313),
aspm = c(4.582104, 0.490244, 0.737765, 0.256699, 1.575931, 1.062693,
1.006984, 0.590355, 1.014370, 0.924855, 0.735989, 0.831025,
1.197886, 1.143220, 0.928068))
str.col.light.blue <- c(rgb(r = 110/255, g = 155/255, b = 225/255))
str.col.dark.blue <- c(rgb(r = 50/255, g = 100/255, b = 185/255))
layout(matrix(c(2, 4, 1, 3), 2, 2, byrow = TRUE), widths = c(5, 2), heights = c(2, 5))
layout.show(4)
par(omi = c(0.1, 0.1, 0.1, 0.1))
par(mar = c(2, 2, 0, 0))
par(mai = c(1, 1, 0, 0))
plot(df.data[, "ll"] ~ df.data[, "aspm"], col = str.col.light.blue,
xlim = c(0, 20), ylim = c(-15, -5), axes = FALSE,
xlab = "X1", ylab = "X2",
cex.lab = 1.25)
abline(a = -8.156670, b = -0.000879, lty = 5, col = "black", lwd = 2, xpd = FALSE)
axis(1, at = seq(0, 20, by = 5), labels = seq(0, 20, by = 5), cex.axis = 1)
axis(2, at = seq(-15, -5, by = 3), labels = seq(-15, -5, by = 3), cex.axis = 1, las = 1)
rect(0, -15, 20, log(1/3)*8, density = 10, angle = 45, lwd = 0.5, col = "gray")
par(mar = c(0, 2, 0, 0))
par(mai = c(0, 1, 0.25, 0))
x.hist <- hist(df.data[, "aspm"], plot = FALSE, breaks = 20)
barplot(x.hist$density, axes = FALSE, horiz = FALSE, space = 0, col = str.col.dark.blue)
par(mar = c(2, 0, 0, 0))
par(mai = c(1, 0, 0, 0.25))
y.hist <- hist(df.data[, "ll"], plot = FALSE, breaks = 20)
barplot(y.hist$density, axes = FALSE, horiz = TRUE, space = 0, col = str.col.dark.blue)
In order to avoid working out the start and end points of the segments, you can program a helper function to do it for you.
linear <- function(x, a, b) a + b*x
Then, I've used your code with the following changes. abline was replaced by segments, with all the graphics parameters you had used in your original call.
x0 <- 0
y0 <- linear(x0, a = -8.156670, b = -0.000879)
x1 <- 20
y1 <- linear(x1, a = -8.156670, b = -0.000879)
segments(x0, y0, x1, y1, lty = 5, col = "black", lwd = 2, xpd = FALSE)
This call to segment was placed where ablinewas.
In the final graph, I see a well behaved segment.
I want to display two plots with the same x-values above each other. But the plots don't align.
How can I align them?
Code:
dat <- data.frame(d = LETTERS[1:5], c = c(39, 371, 389, 378, 790), r = c(39,
332, 18, -11, 412))
par(mfrow=c(2,1))
plot(dat$c, type = "s", ylim = c(0, max(dat$c)), xlab = "", ylab = "", axes = FALSE, col = "#4572a7", lwd = 2)
axis(1, at = c(1:length(dat$c)), labels = dat$d, lty = 0)
axis(2, lty = 0, las = 1)
barplot(dat$r, names.arg = dat$d, col = "#008000", border = NA, axes = FALSE)
axis(2, lty = 0, las = 1)
abline(h = 0, col = "#bbbbbb")
We need to get the x-coordinates of the center of each bar and use those coordinates as the x-values of the first plot. We also need to set the same xlim values for each plot:
# Get x coordinates of center of each bar
pr = barplot(dat$r, names.arg = dat$d, col = "#008000", border = NA, axes = FALSE,
plot=FALSE)
par(mfrow=c(2,1))
# Apply the x coordinates we just calculated to both graphs and give both
# graphs the same xlim values
plot(pr, dat$c, type = "s", ylim = c(0, max(dat$c)), xlab = "", ylab = "", axes = FALSE,
col = "#4572a7", lwd = 2, xlim=range(pr) + c(-0.5,0.5))
axis(1, at = pr, labels = dat$d, lty = 0)
axis(2, lty = 0, las = 1)
barplot(dat$r, names.arg = dat$d, col = "#008000", border = NA, axes = FALSE,
xlim=range(pr) + c(-0.5,0.5))
axis(2, lty = 0, las = 1)
The package UsingR has some great out of the box plotting tools. However, using the simple.scatterplot function I can't figure out how to add axis labels.
library(UsingR)
simple.scatterplot(iris$Sepal.Length, iris$Sepal.Width, xlab='hello axis')
Error in plot.default(x, y, xlim = xrange, ylim = yrange, xlab = "x", :
formal argument "xlab" matched by multiple actual arguments
The graph can of course be produced without using the xlab arg, and I tried using the mtext command, but the label ends up in the middle of the page.
mtext(side=1, text='hello axis')
I tried editing the function itself without success either:
mysimple.scatterplot <- function (x, y)
{
def.par <- par(no.readonly = TRUE)
n <- length(x)
xhist <- hist(x, sqrt(n), plot = FALSE)
yhist <- hist(y, sqrt(n), plot = FALSE)
top <- max(c(xhist$counts, yhist$counts))
xrange <- c(min(x), max(x))
yrange <- c(min(y), max(y))
nf <- layout(matrix(c(2, 0, 1, 3), 2, 2, TRUE), c(3, 1),
c(1, 3), TRUE)
layout.show(nf)
par(mar = c(3, 3, 1, 1))
plot(x, y, xlim = xrange, ylim = yrange, xlab = 'Hello X-axis', ylab = 'Hello Y-axis',
...)
abline(lm(y ~ x))
par(mar = c(0, 3, 1, 1))
barplot(xhist$counts, axes = FALSE, ylim = c(0, top), space = 0,
col = gray(0.95))
par(mar = c(3, 0, 1, 1))
barplot(yhist$counts, axes = FALSE, xlim = c(0, top), space = 0,
col = gray(0.95), horiz = TRUE)
par(def.par)
}
The cause is here:
layout.show(nf)
par(mar = c(3, 3, 1, 1)) # <-- Here
plot(x, y, xlim = xrange, ylim = yrange, xlab = 'Hello X-axis', ylab = 'Hello Y-axis',
...)
The margins are changed to a small value thus the labels are not in the plot, they are outside of the area.