Title on a multi-panel plot - r

The following code works perfectly, except for the last line, which appears to be ignored. The code creates a dataframe consisting of three columns and then proceeds to plot the columns on a 2x2 grid. The last line is supposed to give a title to the entire multi-panel plot. However, it has no effect on the outcome. What is wrong? How can I correct it?
p <- c(3, 5, 10, 20, 50, 100)
n <- c(100, 5000, 100000)
f <- function(x, y){ return ((1 - 2^(-1/y))^(1/x))}
d <- as.data.frame(outer(p, n, FUN = f))
dimnames(d) <- list(p, n)
par(mfrow = c(2,2))
lapply(colnames(d),
function(x) plot(p, d[,x], type = "b",
main = paste("#points = ", x),
xlab = "Dim",
ylab = "Med Dist"))
mtext("Densities", outer = TRUE, cex = 1.5)

Try
par(oma = c(0, 0, 2, 0))
par(mfrow = c(2,2))
lapply(colnames(d),
function(x) plot(p, d[,x], type = "b",
main = paste("#points = ", x),
xlab = "Dim",
ylab = "Med Dist"))
title("Densities", outer=TRUE)

Related

How to demonstrate Kolmogorov-Smirnov statistics's properties with plots in R?

Let be a set of X_1, ..., X_n - independent identically distributed random variables with cumulative distribution function F(x). Let denote the empirical distribution function as F_n(x).
Lets introduce the value Dn (the so-called statistics of the Kolmogorov-Smirnov criterion):
I need to prove with plots that
Dn has a marginal distribution when n\to \infty
The asymptotic distribution of the Dn does not depend on the distribution function F(x)
I tried this, but I don't understand why I get wrong plots (I need basic gtaphic functions or lattice)
`
if (!require("latex2exp")) install.packages("latex2exp")
library("latex2exp")
# 1. Dn has a limit distribution for n -> inf
DNorm <- function(x, mean = 0, sd = 1) {
emp.cdf <- ecdf(x)
n = length(x)
df <- data.frame(emp.cdf = emp.cdf(x), pnorm = pnorm(x, mean, sd))
vec <- (abs((df$emp.cdf - df$pnorm)))
res <- max(vec)* sqrt(n)
}
DnNorm <- function(n, mean = 0, sd = 1) {
x <- sapply(10:n, rnorm, mean, sd)
res <- sapply(x, RNorm, mean, sd)
}
pdf(file="1.pdf")
par(mfrow=c(2,2))
hist(DnNorm(100), breaks = 10, xlim = c(0, 3), col = "cyan1", main = "n = 100", xlab = "Dn")
hist(DnNorm(1000), breaks = 15, xlim = c(0, 3), col = "cyan1", main = "n = 1000", xlab = "Dn")
hist(DnNorm(5000), breaks = 15, xlim = c(0, 3), col = "cyan1", main = "n = 5000", xlab = "Dn")
dev.off()
# 2. Asymptotic distribution of Dn is independent of the distribution function F(x).
pdf(file="2.pdf")
par(mfrow=c(3,1))
hist(DnNorm(3000), breaks = 15, xlim = c(0, 3), col = "cyan1", main = "N(0, 1)", xlab = "Dn")
hist(DnNorm(3000, 50, 4), breaks = 15, xlim = c(0, 3), col = "cyan1", main = "N(50, 4)", xlab = "Dn")
hist(DnNorm(3000, 1), breaks = 15, xlim = c(0, 3), col = "cyan1", main = "EXP(1)", xlab = "Dn")
dev.off()
`
#Yana Sal Maybe you need to correct the line in function DnNorm with:
{res <- sapply(x, DNorm, mean, sd)} # replace RNorm with your function DNorm()`

How to move y-axis labels away from R plot using lapply in R

I have the following code (Thanks to an answer from #Rawr in this question):
labes1 <- c("P(LNG)","","Volume(LNG)","","P(oil)","","Can.GDP","","US GDP","")
titles <- c("Levels","","","","","Log Difference","","","","")
par(mfrow = c(5, 2), mar = c(0.3, 6, 0, 2), oma = c(5, 0, 3, 2))
lapply(1:10, function(ii) {
x <- plotdata1[, ii, drop = FALSE]
plot(x, xlab = "Quarter", ylab = labes1[ii], axes = FALSE)
axis(2, las = 1)
box()
if (ii %in% 9:10) {
axis(1)
title(xlab = 'Quarter', xpd = NA)
}
if (ii %in% 1:2)
title(main = c('Levels', 'Log Difference')[ii], xpd = NA, line = 1)
})
This produces the following plot:
The obvious issue is the overlaying of the y-axis labels with the y-axis values. I have tried playing around with the mar() and oma() but these just change the margins around, I was hoping this would move things out of the way. How can I move the y-axis labels as separate from the plot? I will also be moving the margins a bit so that the white space between the two columns of plots will be closer together.
You can define the ylab separately, like what you're doing for the xlab, and set the line parameter to define its distance from the plot (as stated in this post).
I got a running example from combining your code and #rawr's from your previous question.
set.seed(1)
z <- ts(matrix(rt(200 * 10, df = 3), 200, 10), start = c(1961, 1), frequency = 12)
z <- z * 1e5 # to make "wide" y-axis labels
## vectors of x, y, and main labels
xl <- sprintf('x label %s', 1:10)
yl <- sprintf('y label %s', 1:10)
ml <- sprintf('main label %s', 1:10)
labes1 <- c("P(LNG)","","Volume(LNG)","","P(oil)","","Can.GDP","","US GDP","")
titles <- c("Levels","","","","","Log Difference","","","","")
par(mfrow = c(5, 2), mar = c(0.3, 6, 0, 2), oma = c(5, 0, 3, 2))
lapply(1:10, function(ii) {
x <- z[, ii, drop = FALSE]
plot(x, xlab = "Quarter", ylab = "", axes = FALSE) # set ylab to ""
axis(2, las = 1)
title(ylab = labes1[ii], line = 4) # set the line at an appropriate distance
box()
if (ii %in% 9:10) {
axis(1)
title(xlab = 'Quarter', xpd = NA)
}
if (ii %in% 1:2)
title(main = c('Levels', 'Log Difference')[ii], xpd = NA, line = 1)
})
The code above outputs the following graph for line = 4 :
and this plot for line = 3 :

R plot3d color gardient legend

I am having a 3D plot in which the points are colored acording to some extra vector. My problem is to add a color gradient legend. This is my code:
x = matrix(NA,100,6)
#x value
x[,1] = runif(100, 0, 10)
#y value
x[,2] = runif(100, 0, 10)
#z value
x[,3] = x[,1]+x[,2]
#additional value
x[,4] = runif(100, 0, 1)
#find out in which interval each additional value is
intervals = seq(0,1,1/10)
x[,5] = findInterval(x[,4], intervals)
colours = topo.colors(length(intervals))
x[,6] = colours[x[,5]]
library(rgl)
plot3d(as.numeric(x[,1]),as.numeric(x.stab.in[,2]), as.numeric(x[,3]),
type="p", col=x[,6], size=2, xlab = "x(t)", ylab = "y(t)",
zlab = "z(t)")
decorate3d(xlab = "x", ylab = "y", zlab = "z")
legend3d("topright", legend = intervals, pch = 16, col = colours, cex=1, inset=c(0.02))
grid3d(c("x", "y+", "z"),col = "gray")
The plot looks like this
but I want the legend in a gradient form. That means I don't want separate points for each color but one box in which the colors fade into each other.
Here is a possible solution if you are okay with using scatterplot3d package instead of rgl. It is basically same but non-interactive. Here is your code modified to produce your expected result.
x = matrix(NA,100,6)
#x value
x[,1] = runif(100, 0, 10)
#y value
x[,2] = runif(100, 0, 10)
#z value
x[,3] = x[,1]+x[,2]
#additional value
x[,4] = runif(100, 0, 1)
#find out in which interval each additional value is
intervals = seq(0,1,1/10)
x[,5] = findInterval(x[,4], intervals)
#produce gradient of colors
#you can define different colors (two or more)
gradient <- colorRampPalette(colors = c("yellow", "green", "blue"))
colours <- gradient(length(intervals))
x[,6] = colours[x[,5]]
library(scatterplot3d)
png('3d.png', width = 600, height = 400)
layout(matrix(1:2, ncol=2), width = c(3, 1), height = c(1, 1))
scatterplot3d(as.numeric(x[,1]),as.numeric(x[,2]), as.numeric(x[,3]), type = 'p',
cex.symbols = 1.25, color=x[,6], pch = 16, xlab = "x(t)", ylab = "y(t)", zlab = "z(t)")
plot(x = rep(1, 100), y = seq_along(x[,6]),
pch = 15, cex = 2.5,
col = gradient(length(x[,6])),
ann = F, axes = F, xlim = c(1, 2))
axis(side = 2, at = seq(1, nrow(x), length.out = 11),
labels = 1:11,
line = 0.15)
dev.off()
This will plot the following graph
Here is another solution if you want to plot a gradient on an interactive 3d plot, such as if you needed to animate the plot into a movie.
require(car)
require(rgl)
require(RColorBrewer)
require(mgcv)
require(magick) #Only for creating the animation of the plot as a gif
#Creating mock dataset
Example_Data <- data.frame(Axis1 = rnorm(100),
Axis2 = rnorm(100),
Axis3 = rnorm(100))
Example_Data$Value <- Example_Data$Axis1+Example_Data$Axis2
#Defining function that takes a vector of numeric values and converts them to
#a spectrum of rgb colors to help color my scatter3d plot
get_colors <- function(values){
v <- (values - min(values))/diff(range(values))
x <- colorRamp(rev(brewer.pal(11, "Spectral")))(v)
rgb(x[,1], x[,2], x[,3], maxColorValue = 255)
}
#Writing function that takes a vector of numeric values and a title and creates
#a gradient legend based on those values and the title and suitable for addition
#to a scatter3d plot via a call to bgplot3d()
#Note, I didn't have time to make this automatically adjust text position/size for different size
#plot windows, so values may need to be adjusted manually depending on the size of the plot window.
gradient_legend_3d <- function(values, title){
min_val <- min(values)
max_val <- max(values)
x <- colorRamp(brewer.pal(11, "Spectral"))((0:20)/20)
colors <- rgb(x[,1], x[,2], x[,3], maxColorValue = 255)
legend_image <- as.raster(matrix(colors, ncol=1))
plot(c(0,1),c(0,1),type = 'n', axes = F,xlab = '', ylab = '', main = '') #Generates a blank plot
text(x=0.92, y = seq(0.5, 1,l=5), labels = signif(seq(min_val, max_val,l=5), 2), cex = 1.5) #Creates the numeric labels on the scale
text(x = 0.85, y = 1, labels = title, adj = 1, srt = 90, cex = 1.5) #Determines where the title is placed
rasterImage(legend_image, 0.87, 0.5, 0.9,1) #Values can be modified here to alter where and how wide/tall the gradient is drawn in the plotting area
}
#Creating scatter3d plot
scatter3d(x = Example_Data$Axis1, y = Example_Data$Axis2, z = Example_Data$Axis3, xlab = "Axis1", ylab = "Axis2", zlab = "Axis3", surface = F, grid = F, ellipsoid = F, fogtype = "none", point.col = get_colors(Example_Data$Value))
#Changing size of plotting window and orientation to optimize for addition of static legend
#This may not work on another machine, so the window may need to be adjusted manually
par3d(windowRect = c(0,23,1536,824))
par3d(userMatrix = matrix(c(-0.98181450, -0.02413967, 0.18830180, 0, -0.03652956, 0.99736959, -0.06260729, 0, -0.18629514, -0.06834736, -0.98011345, 0, 0, 0, 0, 1), nrow = 4, ncol = 4, byrow = T))
#Adding legend
bgplot3d(gradient_legend_3d(Example_Data$Value, "Point Value"))
#Animating plot and saving as gif
movie3d(spin3d(axis = c(0,1,0), rpm = 5), duration = 12, dir = getwd(), fps = 5, convert = FALSE, clean = FALSE)
frames <- NULL
for(j in 0:60){
if(j == 1){
frames <- image_read(sprintf("%s%03d.png", "movie", j))
} else {
frames <- c(frames, image_read(sprintf("%s%03d.png", "movie", j)))
}
}
animation <- image_animate(frames, fps = 10, optimize = TRUE)
image_write(animation, path = "Example.gif")
for(j in 0:60){
unlink(sprintf("%s%03d.png", "movie", j))
}
See link to view 3d plot generated by this code:
gif of 3d plot with gradient color scale

Specifying axes in base plot for multiple plots

I'm trying to make a plot with specific axes, while keeping the aspect ratio as 1.
the problem is there is parts of the plot that i don't need and want to remove.
I can manage it using margin:
## Creating Data
x <- seq(1, 100, length.out = 100)
y <- seq(1, 400, length.out = 100)
## Playing with margins
par(fin = c(3.75, 5.3) , mar = c(2, 9, 1, 3) + 0.1 )
## Making
plot(y ~ x ,asp = 1)
abline(v = -10)
abline(v = 120)
But if i want to plot multiple plots i dont know how to remove it
## Using mfrow
par(mfrow = c(3,2))
for (i in 1:6) {
plot(y ~ x ,asp = 1,xlim = c(0,100), ylim = c(0,400))
abline(v = -10)
abline(v = 120)
}
How can i do it for the multiple plots?
This might be closer, using the layout method (see this question and layout R documentation):
x <- seq(1, 100, length.out = 100)
y <- seq(1, 400, length.out = 100)
plot.new()
par(mai = c(0.6,0.5,0.3,0.3))
layout(matrix(c(1,2,3,4,5,6), nrow = 2, ncol = 3, byrow = TRUE))
for (i in 1:6) {
plot(y ~ x ,asp = 1, ylim = c(0,400))
abline(v = -10)
abline(v = 120)
}
The par(mai=c(b,l,t,r)) option changes the size of the whitespace surrounding the subplots.

R: Difference between log axis scale vs. manual log transformation?

set.seed(2)
x = c(1, rnorm(100, 15, 5))
y = c(1, rnorm(100, 15, 5))
plot(x, y, log = "xy")
plot(log(x), log(y))
What is the difference when i use log-argument in plot() function and when i transform the variables first, then plot them. Hier is the plot with plot(x, y, log = "xy").
And with plot(log(x), log(y))
Can someone explain me what does the log-argument exactly do? Thank you.
For log-plots you do not have to modify your data. It is just a matter of displaying, so that you can further work with your data. Just as example:
set.seed(2)
x = c(1, rnorm(100, 15, 50))
y = c(1, rnorm(100, 15, 50))
plot(x, y, col = "black",
log = "xy", xaxt = "n", yaxt = "n",)
# Labels...
at.y <- outer(1:9, 10^(log10(1):log10(100)))
lab.y <- ifelse(log10(at.y) %% 1 == 0,
sapply(at.y, function(i)
as.expression(bquote(10^.(log10(i))))
), NA)
axis(2, at = at.y, labels = lab.y, las = 1)
at.x <- outer(1:9, 10^(0:log10(100)))
lab.x <- ifelse(log10(at.x) %% 1 == 0,
sapply(at.x, function(i)
as.expression(bquote(10^.(log10(i))))
), NA)
axis(1, at = at.x, labels = lab.x, las = 1)
grid (NULL,NULL, lty = 6, col = "cornsilk2")
Result:

Resources