Not able to combine special plots with par - r

I have been trying to combine plots in one image by using par(). I am able to do so for histograms etc., but not for these plots. Do you have any idea why?
I tried reading up but did not find any solution. Does it have something with base R (or the graphics package) not being able to handle the plots exported by forest.meta()?
a <- c("a","b","c", "d", "e", "f")
b <- c(1,2,3,4,5,6)
c <- c(2,2,3,4,5,6)
d <- c(4,5,6,7,8,9)
df <- data.frame(a,b,c,d)
library(meta)
metta <- metaprop(event = df$b, n = df$d, studlab = df$a, data = df)
metta2 <- metaprop(event = df$c, n = df$d, studlab = df$a, data = df)
par(mfrow=c(2,1))
meta::forest.meta(metta)
meta::forest.meta(metta2)

Related

number of items to replace is not a multiple of replacement length + several plots in same graph error

I'm trying to draw several plots in the same graph in Rstudio, but to no avail. This is the code I'm using:
for (i in 1:10){
require(ggplot2)
N <- 100
T <- 3
Delta <- T/N
B <- numeric(N+1)
t <- seq(0,T,length=N+1)
for(i in 2:(N+1)){
B[i] <- B[i-1]+rnorm(1) * sqrt(Delta)
}
x <- 0
y <- 3
BB[i] <- x+B-(t/T)*(B[N+1]-y+x)
df <- melt(data = BB, id.vars = "t")
ggplot(data = df, aes(x = t, y = value, colour = variable)) + geom_line()
}
Using ggplot2 as I seen recomended in several Stackoverflow post yieds "number of items to replace is not a multiple of replacement length".
I've seen several answers to that question but being quite a noob in R I don't see how it applies to my problem. Please and thank you in advance.
How about this:
BB <- list() # define BB as a list
for (i in 1:10){
require(ggplot2)
N <- 100
T <- 3
Delta <- T/N
B <- numeric(N+1)
t <- seq(0,T,length=N+1)
for(q in 2:(N+1)){ # Change your index from i to q
B[q] <- B[q-1]+rnorm(1) * sqrt(Delta)
}
x <- 0
y <- 3
BB[[i]] <- x+B-(t/T)*(B[N+1]-y+x) # Assign each iteration to a list entry
}
# Exit the for loop
df <- as.data.frame(cbind(unlist(BB), # unlist the values in BB
rep(t,10), # define t variable by simply repeating it
rep(1:10,each= 101))) # define loop id in a similar manner
names(df) <- c('value','t','variable') # give names to the variables
df$variable <- as.factor(df$variable) # turn variable into a factor
ggplot(data = df, aes(x = t, y = value, colour = variable)) + geom_line()
The resulting plot:

Jitter dots without overlap

My data:
a <- sample(1:5, 100, replace = TRUE)
b <- sample(1:5, 100, replace = TRUE)
c <- sample(1:10, 100, replace = TRUE)
d <- sample(1:40, 100, replace = TRUE)
df <- data.frame(a, b, c, d)
Using ggplot2, I have created scatterplot over x = a and y = b, weighted in two dimension (by colour = c and size = d). Note that x and y are intentionally 1:5.
Obviously, the points of different sizes and colors therefore overlap, so I tried jitter to avoid overlapping:
ggplot(df, aes(a, b, colour = c, size = d)) +
geom_point(position = position_jitter())
Now I would like the dots clustering closer together, so I tried several
combinations of height and width for the jitter function, such as
ggplot(df, aes(a, b, colour = c, size = d)) +
geom_point(position = position_jitter(width = 0.2, height = 0.2))
Jitter makes the dots still overlap and also distributes them to randomly on the given area.
Is there a way to have the dots not overlapping at all, yet clustered as close together as possible, maybe even touching and also not "side by side" or stacked? (In a way, creating kind of bubbles with smaller dots)?
Thanks!
According to #Tjebo's suggestions I have arranged dots in "heaps".
set.seed(1234)
n <- 100
a <- sample(1:5,n,rep=TRUE)
b <- sample(1:5,n,rep=TRUE)
c <- sample(1:10,n,rep=TRUE)
d <- sample(1:40,n,rep=TRUE)
df0 <- data.frame(a,b,c,d)
# These parameters need carefully tuning
minr <- 0.05
maxr <- 0.2
# Order circles by dimension
ord <- FALSE
df1 <- df0
df1$d <- minr+(maxr-minr)*(df1$d-min(df1$d))/(max(df1$d)-min(df1$d))
avals <- unique(df1$a)
bvals <- unique(df1$b)
for (k1 in seq_along(avals)) {
for (k2 in seq_along(bvals)) {
print(paste(k1,k2))
subk <- (df1$a==avals[k1] & df1$b==bvals[k2])
if (sum(subk)>1) {
subdfk <- df1[subk,]
if (ord) {
idx <- order(subdfk$d)
subdfk <- subdfk[idx,]
}
subdfk.mod <- subdfk
posmx <- which.max(subdfk$d)
subdfk1 <- subdfk[posmx,]
subdfk2 <- subdfk[-posmx,]
angsk <- seq(0,2*pi,length.out=nrow(subdfk2)+1)
subdfk2$a <- subdfk2$a+cos(angsk[-length(angsk)])*(subdfk1$d+subdfk2$d)/2
subdfk2$b <- subdfk2$b+sin(angsk[-length(angsk)])*(subdfk1$d+subdfk2$d)/2
subdfk.mod[posmx,] <- subdfk1
subdfk.mod[-posmx,] <- subdfk2
df1[subk,] <- subdfk.mod
}
}
}
library(ggplot2)
library(ggforce)
ggplot(df1, aes()) +
geom_circle(aes(x0=a, y0=b, r=d/2, fill=c), alpha=0.7)+ coord_fixed()
An interesting visualization tool is the beeswarm plot.
In R the beeswarm and the ggbeeswarm packages implement this kind of plot.
Here is an example with ggbeeswarm:
set.seed(1234)
a <- sample(1:5,100,rep=TRUE)
b <- sample(1:5,100,rep=TRUE)
c <- sample(1:10,100,rep=TRUE)
d <- sample(1:40,100,rep=TRUE)
df <- data.frame(a,b,c,d)
library(ggbeeswarm)
ggplot(aes(x=a, y=b, col=c, size=d), data = df)+
geom_beeswarm(priority='random',cex=3.5, groupOnX=T)+coord_flip()
I hope this can help you.
Here is another possibile solution to the jittering problem of #Tjebo.
The parameter dst needs some tuning.
set.seed(1234)
a <- sample(1:5,100,rep=TRUE)
b <- sample(1:5,100,rep=TRUE)
c <- sample(1:10,100,rep=TRUE)
d <- sample(1:40,100,rep=TRUE)
df <- data.frame(a,b,c,d)
dst <- .2
df.mod <- df
avals <- unique(df$a)
bvals <- unique(df$b)
for (k1 in seq_along(avals)) {
for (k2 in seq_along(bvals)) {
subk <- (df$a==avals[k1] & df$b==bvals[k2])
if (sum(subk)>1) {
subdf <- df[subk,]
angsk <- seq(0,2*pi,length.out=nrow(subdf)+1)
ak <- subdf$a+cos(angsk[-1])*dst
bk <- subdf$b+sin(angsk[-1])*dst
df.mod[subk,c("a","b")] <- cbind(ak,bk)
}
}
}
library(ggplot2)
ggplot(df.mod, aes(a, b, colour = c, size = d)) + geom_point()

Plot 3D prisms using ggplot2 and plotly

I have a list a with three matrices and a vector h with three heights (any positive real number). These matrices form triangles, that is, the base of the prism. I want to add the information of vector h to construct prisms.
I've created a function to plot graphics in 2D (pplot). How can I plot the prisms as in the figure below?
Let pplot and a toy problem be an example:
library(ggplot2)
pplot <- function(polygon){
polygon <- lapply(polygon, function(x) {colnames(x) <- NULL; x})
vertex_number = nrow(polygon[[1]])
g = ggplot2::ggplot()
names(polygon) = 1:length(polygon)
k <- plyr::ldply(polygon, function(x) data.frame(x))
g <- ggplot2::ggplot(k, ggplot2::aes(x = X1, y = X2, group = .id)) + ggplot2::geom_polygon(colour = "black", fill = NA)
return(g)
}
a <- list()
b1 <- matrix(rnorm(6), ncol = 2)
b2 <- matrix(rnorm(6), ncol = 2)
b3 <- matrix(rnorm(6), ncol = 2)
a[[1]] <- b1
a[[2]] <- b2
a[[3]] <- b3
h <- c(.3, .5, .1)
#pplot function example
pplot(a)
Graphic desired
Where the coordinate a = d, b = f, c = e are vertices and all information is in a.
Observation 1: The data must a list.
Observation 2: I've created a post in portuguese, but nobody answered. Can I do this or it is cheating? (I'm new here)
https://pt.stackoverflow.com/questions/165538/plotar-figuras-3d-para-dados-em-lista
I'm not 100% sure I understood the task correctly. Nevertheless here's a draft for a solution with the package rgl. In my opinion it's still the best 3D plotting framework for R, because it's much faster and scales better than the javascript APIs (plotly, rthreejs etc.).
#### load package rgl ####
library(rgl)
set.seed(1232)
#### construct test list with coordinate matrices ####
a <- list()
b1 <- matrix(rnorm(6), ncol = 2)
b2 <- matrix(rnorm(6), ncol = 2)
b3 <- matrix(rnorm(6), ncol = 2)
a[[1]] <- b1
a[[2]] <- b2
a[[3]] <- b3
#### define test height vector ####
h <- c(.3, .5, .1)
#### simple plot prism function ####
# a: list with coordinate matrices
# h: height vector
plotprism <- function(a, h){
# general loop to plot every prism
for(i in 1:length(h)){
# transform matrizes to data.frames and add height column
# -> separation of top and bottom triangle
top <- data.frame(a[[i]], h[i])
bottom <- data.frame(a[[i]], 0)
# adjust colnames to axis names
colnames(top) <- c("x", "y", "z")
colnames(bottom) <- c("x", "y", "z")
# plot triangles (as wireframes)
triangles3d(bottom, front = "line", back = "line")
triangles3d(top, front = "line", back = "line")
# plot vertical lines to connect the triangles
for(i in 0:2){
segments3d(
x = c(bottom$x[1+i], top$x[1+i]),
y = c(bottom$y[1+i], top$y[1+i]),
z = c(bottom$z[1+i], top$z[1+i])
)
}
}
#### add coordinate system ####
axes3d()
}
#### call plot function for test data ####
plotprism(a, h)
The results:

append pdf file in R - dev.off() [duplicate]

This question already has answers here:
Plotting over multiple pages
(2 answers)
Closed 9 years ago.
How can I keep saving figures to a pdf with R. Consider the following example:
require(ggplot2)
require(gridExtra)
TopFolder <- "...directory on my drive"
setwd(TopFolder)
pdf(file = paste(TopFolder,"figures","example.pdf",sep = "\\"))
g <- list()
for(i in 1:4){
dat <- data.frame(d1 = c(1:10),
d2 = runif(10))
g[[i]] <- qplot(x = d1, y = d2,
data = dat)
}
grid.arrange(g[[1]],g[[2]],g[[3]],g[[4]])
for(i in 1:6){
dat <- data.frame(d1 = c(1:20),
d2 = runif(20))
qplot(x = d1, y = d2,
data = dat)
}
dev.off()
My question is: Why doesn't the sesond set of plots i.e. the 6 generated by the second for loop show up in the pdf file? The only obvious difference I can spot is that I store the plots in the first loop and do't in the second. Why doesn't R generate these plots in the second loop and save them in the pdf after completion?
The result I would expect from this example would be to have the first page of the pdf with the four subplots and then have 6 pages following with one figure in each page. Why isn't this being generated? I would have thought that R would keep generating the figures in the file until dev.off() was called?
... and all putting all commands from above together
require(ggplot2)
require(gridExtra)
TopFolder <-"...directory on my drive"
setwd(TopFolder)
pdf(file = file.path(TopFolder,"figures","example.pdf"), onefile=TRUE)
g <- list()
for(i in 1:4){
dat <- data.frame(d1 = c(1:10),
d2 = runif(10))
g[[i]] <- qplot(x = d1, y = d2,
data = dat)
}
grid.arrange(g[[1]],g[[2]],g[[3]],g[[4]])
gg <- list()
# each of this plots will be on a separate page
for(i in 1:6){
dat <- data.frame(d1 = c(1:20),
d2 = runif(20))
# here a print is necessary
print(qplot(x = d1, y = d2,
data = dat))
}
dev.off()

Matrix of density plots with each plot overlaying two distributions

I have a data.frame with 5 columns and I'd like to generate a matrix of density plots, such that each density plot is an overlay of two density plots. (This is akin to plotmatrix, except that in my case, the number of non-NA value in each column differ from column to column and I want overlaid distributions rather than scatter plots).
My first attempt, which didn't work, is given below:
library(ggplot2)
library(reshape)
tmp1 <- data.frame(do.call(cbind, lapply(1:5, function(x) {
r <- rnorm(100)
r[sample(1:100, 20)] <- NA
return(r)
})))
ggplot( melt(tmp1), aes(x=value, fill=variable))+
geom_density(alpha=0.2, position="identity")+opts(legend.position = "none")+
facet_grid(variable ~ variable)
My second approach got me nearly there, but instead of 5 different colors, I only want to use two colors across all the plots. And, I'm sure there is a more elegant way to construct this expanded matrix:
tmp2 <- do.call(rbind, lapply(1:5, function(i) {
do.call(rbind, lapply(1:5, function(j) {
r <- rbind(data.frame(var=sprintf('X%d', i), val=tmp1[,i]),
data.frame(var=sprintf('X%d', j), val=tmp1[,j]))
r <- data.frame(xx=sprintf('X%d', i), yy=sprintf('X%d', j), r)
return(r)
}))
}))
ggplot(tmp2, aes(x=val, fill=var))+
geom_density(alpha=0.2, position="identity")+opts(legend.position = "none")+
facet_grid(xx ~ yy)
My solution was to manually loop through the pairs of columns and generate the overlaid density plots by hand, saving them to a list. I then arranged them in a grid using `grid.arrange' giving the image below.
But is it possible to achieve this using facet_grid instead?
The easiest way is to reshape your data with all permutations (5 * 5 = 25 of them).
require(gregmisc)
perm <- permutations(5, 2, paste0("X", 1:5), repeats.allowed=TRUE)
# instead of gregmisc + permutations, you can use expand.grid from base as:
# perm <- expand.grid(paste0("X", 1:5), paste0("X", 1:5))
o <- apply(perm, 1, function(idx) {
t <- tmp1[idx]
names(t) <- c("A", "B")
t$id1 <- idx[1]
t$id2 <- idx[2]
t
})
require(ggplot2)
require(reshape2)
o <- do.call(rbind, o)
o.m <- melt(o, c("id1", "id2"))
o.m$id1 <- factor(o.m$id1)
o.m$id2 <- factor(o.m$id2)
p <- ggplot(o.m, aes(x = value))
p <- p + geom_density(alpha = 0.2, position = "identity", aes(fill = variable))
p <- p + theme(legend.position = "none")
p <- p + facet_grid(id1 ~ id2)
p

Resources