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.
Related
My example data is as follows:
df <- data.frame(study = c("Hodaie","Kerrigan","Lee","Andrade","Lim"), SR = c(0.5460, 0.2270, 0.7540, 0.6420, 0.5000), SE = c(12.30, 15.70, 12.80, 13.80, 9.00), Patients = c(5, 5, 3, 6, 4))
I want to conduct the meta-analysis with SR(single group percentage), SE (standard error that I can compute based on sample size and percentage), and patients(sample size for each study), and I hope I could get the following forest plot (I found this example in an article, and they also have one group percentage data, but I can't find which R statement or argument they used):
Could anyone tell me which R statement or argument that I could use to conduct the meta-analysis and generate the forest plot above? Thank you!
I am sure there are plenty of ways to do this using packages but it can be accomplished in base R (and there are likely more elegant solutions using base R). The way I do it is to first build a blank plot much larger than the needed graphing portion, then overlay the relevant elements on it. I find one has more control over it this way. A basic example that could get you started is below. If you are new to R (based on your name NewRUser), I suggest running it line-by-line to see how it all works. Again, this is only one way and there are likely better approaches. Good luck!
Sample Data
#### Sample Data (modified from OP)
df <- data.frame(Study = c("Hodaie","Kerrigan","Lee","Andrade","Lim"),
SR = c(0.5460, 0.2270, 0.7540, 0.6420, 0.5000),
SE = c(12.30, 15.70, 12.80, 13.80, 9.00),
Patients = c(5, 5, 3, 6, 4),
ci_lo = c(30, -8.0, 50, 37, 32),
ci_hi = c(78, 53, 100, 91, 67))
### Set up plotting elements
n.studies <- nrow(df)
yy <- n.studies:1
seqx <- seq(-100, 100, 50)
## blank plot much larger than needed
plot(range(-550, 200), range(0, n.studies), type = 'n', axes = F, xlab = '', ylab = '') #blank plot, much bigger than plotting portion needed
# Set up axes
axis(side = 1, at = seqx, labels = seqx, cex.axis = 1, mgp = c(2, 1.5, 1)) # add axis and label (bottom)
mtext(side = 1, at = 0, 'Seizure Reduction', line = 2.5, cex = 0.85, padj = 1)
axis(side = 3, at = seqx, labels = seqx, cex.axis = 1, mgp = c(2, 1.5, 1)) # add axis and label (top)
mtext(side = 3, at = 0, 'Seizure Reduction', line = 2.5, cex = 0.85, padj = -1)
## add lines and dots
segments(df[, "ci_lo"], yy, df[,"ci_hi"], yy) # add lines
points(df[,"SR"]*100, yy, pch = 19) # add points
segments(x0 = 0, y0 = max(yy), y1 = 0, lty = 3, lwd = 0.75) #vertical line # 0
### Add text information
par(xpd = TRUE)
text(x = -550, y = yy, df[,"Study"], pos = 4)
text(x = -450, y = yy, df[,"SR"]*100, pos = 4)
text(x = -350, y = yy, df[,"SE"], pos = 4)
text(x = -250, y = yy, df[,"Patients"], pos = 4)
text(x = 150, y = yy, paste0(df[,"ci_lo"], "-", df[,"ci_hi"]), pos = 4)
text(x = c(seq(-550, -250, 100), 150), y = max(yy)+0.75,
c(colnames(df)[1:4], "CI"), pos = 4, font = 2)
# Add legend
legend(x = 50, y = 0.5, c("Point estimate", "95% Confidence interval"),
pch = c(19, NA), lty = c(NA, 19), bty = "n", cex = 0.65)
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 :
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:
I'm wondering how to do this graph in R?
I tought about using geom_bar from the ggplot package. However I don't know how to plot the changing thickness and the colors that reflect the growth for the years at the same time.
I'd appreciate any ideas.
Thank you.
Here are some steps to start. Nothing special, just some rectangles. There is a lot of information going on in this chart, most of it is in the text along the sides, usually meaning that the chart isnt very effective.
The only useful info the chart really shows is the yearly change in colors. You can do something like that below where I colored based on the rectangle height.
But +1 for finding another way to visualize your data.
set.seed(1)
nr <- 4
nc <- 50
mm <- matrix(sort(runif(nr * nc)) * 10, nr, nc)
nn <- matrix(sort(runif(nr * nc), decreasing = TRUE) * 10, nr, nc)
mm <- do.call('rbind', l <- list(mm, nn))[order(sequence(sapply(l, nrow))), ]
yy <- 50
mm <- rbind(mm, yy - colSums(mm))
nr <- nrow(mm)
plot(0:nc, type = 'n', ylim = c(0, yy), bty = 'n', axes = FALSE, ann = FALSE)
rect(s <- sequence(nc), 0, s + .95, mm[1, ], border = NA,
col = as.numeric(cut(mm[1, ], breaks = seq(0, 15, 3))))
axis(1, s + .5, labels = s + 2000, lwd = 0, lwd.ticks = 1)
axis(1, s, labels = NA, lwd = 0, lwd.ticks = .5, tcl = -.2)
# axis(2, las = 1, lwd = 0)
mtext('Share of private jobs', side = 2, at = par('usr')[3], adj = 0)
arrows(.5, 0, .5, yy, lwd = 2, xpd = NA, length = .1)
text(par('usr')[1:2] + c(.5, -.5), yy, labels = range(s) + 2000,
xpd = NA, pos = 3, adj = 0)
yy <- matrix(0, 1, nc)
for (ii in 2:nr) {
yy <- colSums(rbind(yy, mm[ii - 1, ]))
rect(s, yy + 1, s + .95, yy + mm[ii, ], border = NA,
col = as.numeric(cut(mm[ii, ], breaks = seq(0, 15, 3))))
}
(I hope no one submits this to junk charts :{ )
Also here is another incredibly simple way. Should have done this first, ie, create sample data, pad the rows, and let barplot take care of the rest. A lot less control over this approach, though.
mm <- matrix(sort(runif(10)), 2) * 10
nn <- matrix(.5, 2, ncol(mm))
mm <- do.call('rbind', l <- list(mm, nn))[order(sequence(sapply(l, nrow))), ]
yy <- 22
mm <- rbind(mm, yy - colSums(mm))
barplot(mm, col = 1:0, border = NA, axes = FALSE)
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)