legend in a forest plot - r

I am having a hard time with the forest plot package in R. Here is my code. Actually everything works well beside the legend.
. However for the legend, I would like to have a Blue Circle, A red Square and a green losange in stead of 3 squares.
Any idea?
Thanks in advance.
Peter
library(forestplot)
test_data <- data.frame(coef1=c(0.54,0.72,0.57),
coef2=c(0.59,0.79,0.58),
coef3=c(0.49,0.60,0.48),
low1=c(0.41,0.46,0.42),
low2=c(0.44,0.49,0.42),
low3=c(0.37,0.37,0.35),
high1=c(0.72,1.12,0.77),
high2=c(0.78,1.26,0.80),
high3=c(0.65,0.99,0.66))
col_no <- grep("coef", colnames(test_data))
row_names <- list(
list("Behavioral CVH","Biological CVH","Total CVH"))
coef <- with(test_data, cbind(coef1, coef2, coef3))
low <- with(test_data, cbind(low1, low2, low3))
high <- with(test_data, cbind(high1, high2, high3))
forestplot(row_names, coef, low, high,
title="Paris Prospective Study 3",
fn.ci_norm=matrix(c("fpDrawCircleCI", "fpDrawNormalCI","fpDrawDiamondCI"),
nrow = 3, ncol=3, byrow=T),
zero = c(1), boxsize=0.05,
col=fpColors(box=c("royalblue", "gold", "black"),
line=c("darkblue", "orange", "black"),
summary=c("darkblue", "red", "black"),
hrz_lines = "#444444"),
xlab="Odds ratio & 95% Confidence intervals",
vertices = TRUE,
new_page = TRUE,
legend=c("Q2 vs. Q1","Q3 vs. Q1","Q4 vs. Q1"),
legend_args = fpLegend(pos = list("topright"),
title="Legend",
r = unit(0, "snpc"),
gp = gpar(col="#CCCCCC", lwd=1.5)))

One thing you can do is use the "regular" call to legend, outside the call for the forestplot.
To do that, you'll first have to call plot.new:
plot.new()
forestplot(...) # without the legend part
legend("topright", c("Q2 vs. Q1","Q3 vs. Q1","Q4 vs. Q1"), title="Legend", border="#CCCCCC", box.lwd=1.5,
col=c("blue", "red", "green"), pch=c(16, 15, 18))

Related

RDA triplot in R- plot only numeric explanatory variables as arrows; factors as centroids

I ran a distance-based RDA using capscale() in the vegan library in R and I am trying to plot my results as a custom triplot. I only want numeric or continuous explanatory variables to be plotted as arrows/vectors. Currently, both factors and numeric explanatory variables are being plotted with arrows, and I want to remove arrows for factors (site and year) and plot centroids for these instead.
dbRDA=capscale(species ~ canopy+gmpatch+site+year+Condition(pair), data=env, dist="bray")
To plot I extracted % explained by the first 2 axes as well as scores (coordinates in RDA space)
perc <- round(100*(summary(spe.rda.signif)$cont$importance[2, 1:2]), 2)
sc_si <- scores(spe.rda.signif, display="sites", choices=c(1,2), scaling=1)
sc_sp <- scores(spe.rda.signif, display="species", choices=c(1,2), scaling=1)
sc_bp <- scores(spe.rda.signif, display="bp", choices=c(1, 2), scaling=1)
I then set up a blank plot with scaling, axes, and labels
dbRDAplot<-plot(spe.rda.signif,
scaling = 1, # set scaling type
type = "none", # this excludes the plotting of any points from the results
frame = FALSE,
# set axis limits
xlim = c(-1,1),
ylim = c(-1,1),
# label the plot (title, and axes)
main = "Triplot db-RDA - scaling 1",
xlab = paste0("db-RDA1 (", perc[1], "%)"),
ylab = paste0("db-RDA2 (", perc[2], "%)"))
Created a legend and added points for site scores and text for species
pchh <- c(2, 17, 1, 19)
ccols <- c("black", "red", "black", "red")
legend("topleft", c("2016 MC", "2016 SP", "2018 MC", "2018 SP"), pch = pchh[unique(as.numeric(as.factor(env$siteyr)))], pt.bg = ccols[unique(as.factor(env$siteyr))], bty = "n")
points(sc_si,
pch = pchh[as.numeric(as.factor(env$siteyr))], # set shape
col = ccols[as.factor(env$siteyr)], # outline colour
bg = ccols[as.factor(env$siteyr)], # fill colour
cex = 1.2) # size
text(sc_sp , # text(sc_sp + c(0.02, 0.08) tp adjust text coordinates to avoid overlap with points
labels = rownames(sc_sp),
col = "black",
font = 1, # bold
cex = 0.7)
Here is where I add arrows for explanatory variables, but I want to be selective and do so for numeric variables only (canopy and gmpatch). The variables site and year I want to plot as centroids, but unsure how to do this. Note that the data structure for these are definitely specified as factors already.
arrows(0,0, # start them from (0,0)
sc_bp[,1], sc_bp[,2], # end them at the score value
col = "red",
lwd = 2)
text(x = sc_bp[,1] -0.1, # adjust text coordinate to avoid overlap with arrow tip
y = sc_bp[,2] - 0.03,
labels = rownames(sc_bp),
col = "red",
cex = 1,
font = 1)
#JariOksanen thank you for your answer. I was able to use the following to fix the problem
text(dbRDA, choices = c(1, 2),"cn", arrow=FALSE, length=0.05, col="red", cex=0.8, xpd=TRUE)
text(dbRDA, display = "bp", labels = c("canopy", "gmpatch"), choices = c(1, 2),scaling = "species", arrow=TRUE, select = c("canopy", "gmpatch"), col="red", cex=0.8, xpd = TRUE)
#JariOksanen thank you for your answer. I was able to use the following to fix the problem
text(dbRDA, choices = c(1, 2),"cn", arrow=FALSE, length=0.05, col="red", cex=0.8, xpd=TRUE)
text(dbRDA, display = "bp", labels = c("canopy", "gmpatch"), choices = c(1, 2),scaling = "species", arrow=TRUE, select = c("canopy", "gmpatch"), col="red", cex=0.8, xpd = TRUE)

Reducing space between title and pie chart, using R-base

I have created a pie chart and I realize that the title of the pie chart is further away from the pie chart. I want to ask how I can shorten the distance between the title and the chart, using base R.
pie(group3$count, labels = a, col = c("orange", "pink"), main= "The percentage of Fuel type, among Low Emission cluster", cex.main=1 )
legend("bottomright", legend = c("DIESEL/ELECTRIC", "PETROL/ELECTRIC"), fill=c("pink","orange"))
Output:
Many thanks.
You could build the plot separately using legend() and title() and in title call line = 0.6 or any value lower than 1 to move the title closer.
Also I think you are mixing up the colours for either the fill or the legend. one has pink before orange, and the other orange before pink.
automatic <- sum(mtcars$am) / nrow(mtcars)
manual <- 1 - automatic
df <- data.frame(count = c(automatic, manual))
a <- c("Automatic", "Manual")
pie(df$count, col = c("pink", "orange"))
legend(x = "bottomright",
legend = a,
fill = c("pink", "orange"))
title(main = "TITLE", cex.main = 1)
title(main = "TITLE, BUT CLOSER", cex.main = 1, line = 0.6)
Created on 2023-01-09 with reprex v2.0.2

Remove upper axis in plot glmnet

When using glmnet and making a plot of the coefficient path, I would like to remove the axis above the plot.
How do you remove this axis? I found this toy example on the web:
library(glmnet)
age <- c(4,8,7,12,6,9,10,14,7)
gender <- c(1,0,1,1,1,0,1,0,0) ; gender<-as.factor(gender)
bmi_p <- c(0.86,0.45,0.99,0.84,0.85,0.67,0.91,0.29,0.88)
m_edu <- c(0,1,1,2,2,3,2,0,1); m_edu<-as.factor(m_edu)
p_edu <- c(0,2,2,2,2,3,2,0,0); p_edu<-as.factor(p_edu)
f_color <- c("blue", "blue", "yellow", "red", "red", "yellow", "yellow", "red", "yellow")
asthma <- c(1,1,0,1,0,0,0,1,1)
f_color <- as.factor(f_color)
xfactors <- model.matrix(asthma ~ gender + m_edu + p_edu + f_color)[,-1]
x <- as.matrix(data.frame(age, bmi_p, xfactors))
glmmod<-glmnet(x,y=as.factor(asthma),alpha=1,family='binomial')
plot(glmmod,xvar="lambda", axes=FALSE)
This unwanted axis is made with axis function, I guess. We can use this function one more time to cover it. The trick is as follows:
1) Create a sequence with many points at which tick-marks are to be drawn.
2) Make them bigger (lengthen upwards)
3) Enlarge the width of the axis
4) Change the white colour and switch off labels
plot(glmmod, xvar = "lambda", axes = F, xlab = "", ylab = "")
axis(side = 3,
at = seq(par("usr")[1], par("usr")[2], len = 1000),
tck = -0.5,
lwd = 2,
col = "white",
labels = F)

How to increase y-axis in barplot?

My code:
#!/usr/bin/R
layout(matrix(c(1, 1, 2, 2, 3, 3, 4, 4, 5), ncol=1))
# main plots
par(mar=c(5,2,4,2))
fcm <-c(14.0,14.1,13.0,14.2,14.7,13.8,14.0)
gk <-c(12.1,12.5,12.2,12.0,11.5,12.0,11.4)
gg <-c(14.0,14.1,13.3,12.8,12.0,12.2,12.0)
data1 <- rbind(fcm,gk,gg)
colnames(data1) <- c(6,7,8,9,10,11,12)
fcm <-c(2.65,2.55,2.4,2.45,2.45,2.5,2.45)
gk <-c(2.45,2.55,2.4,2.3,2.2,2.35,2.1)
gg <-c(2.6,2.65,2.5,2.35,2.4,2.4,2.2)
data2 <- rbind(fcm,gk,gg)
colnames(data2) <- c(6,7,8,9,10,11,12)
fcm <-c(8.8,6.5,6.6,8.2,8.0,8.4,9.0)
gk <-c(12.7,11.0,11.1,10.5,10.7,10.0,9.5)
gg <-c(2.1,2.1,1.8,2.0,2.0,1.9,1.8)
data3 <- rbind(fcm,gk,gg)
colnames(data3) <- c(6,7,8,9,10,11,12)
fcm <-c(0.47,0.53,0.45,0.39,0.40,0.47,0.48)
gk <-c(0.45,0.51,0.34,0.40,0.42,0.42,0.44)
data4 <- rbind(fcm,gk)
colnames(data4) <- c(6,7,8,9,10,11,12)
barplot(as.matrix(data1),ylim=c(0,15),main="P wave",
xlab="number of clusters", ylab="traveltime rms(ms)",
col=c("red", "black", "green"), beside=TRUE)
barplot(as.matrix(data2),ylim=c(0,3),main="MT",
xlab="number of clusters", ylab="MT functions",
col=c("red", "black", "green"), beside=TRUE)
barplot(as.matrix(data3),ylim=c(0,13),main="XBI",
xlab="number of clusters", ylab="index value",
col=c("red", "black", "green"), beside=TRUE)
barplot(as.matrix(data4),ylim=c(0,0.6),main="NCE",
xlab="number of clusters", ylab="index value",
col=c("red", "black"), beside=TRUE)
par(mai=c(0,0,0,0))
plot.new()
legend(legend = c("fcm","gk","gg"), fill = c( "red", "black", "green"),
"center", horiz=TRUE)
This image will be part of my paper,plan to submit it to a journal.I am afraid editor will complain that values are not visible.How to change this?My goal is that there is clear distinction between all barplots,of course if this is possible.
Stacking your plots is compressing them unnecessarily & creating a lot of wasted white space.
Why not shift to a 2x2 representation?
Basically all you need to change is:
layout(matrix(c(1, 2, 5, 3, 4, 5), ncol=2))
I get this output with par(mar=c(3.1,2.1,2.1,0.1)):
You may notice we're giving too much space to the legend; this can be fixed by tinkering with the heights parameter to layout; here's the output with heights=c(.45,.45,.1). See ?layout.
I prefer #MichaelChirico's answer, but if you need them to be stacked in one column for some reason, here is another option. I've added comments to explain the changes to your original code. Basically, I've created some additional vertical space by playing with the margins and the layout matrix, and getting rid of unnecessary x-axis titles:
# Change layout matrix to allow more vertical space for bottom plot
# (since it is now the only one with an x-axis title)
layout(matrix(1:5, ncol=1), heights=c(rep(0.21,3), 0.26, 0.11))
# main plots
par(mar=c(2,2.5,3.5,2)) # Decrease top and bottom margins
fcm <-c(14.0,14.1,13.0,14.2,14.7,13.8,14.0)
gk <-c(12.1,12.5,12.2,12.0,11.5,12.0,11.4)
gg <-c(14.0,14.1,13.3,12.8,12.0,12.2,12.0)
data1 <- rbind(fcm,gk,gg)
colnames(data1) <- c(6,7,8,9,10,11,12)
fcm <-c(2.65,2.55,2.4,2.45,2.45,2.5,2.45)
gk <-c(2.45,2.55,2.4,2.3,2.2,2.35,2.1)
gg <-c(2.6,2.65,2.5,2.35,2.4,2.4,2.2)
data2 <- rbind(fcm,gk,gg)
colnames(data2) <- c(6,7,8,9,10,11,12)
fcm <-c(8.8,6.5,6.6,8.2,8.0,8.4,9.0)
gk <-c(12.7,11.0,11.1,10.5,10.7,10.0,9.5)
gg <-c(2.1,2.1,1.8,2.0,2.0,1.9,1.8)
data3 <- rbind(fcm,gk,gg)
colnames(data3) <- c(6,7,8,9,10,11,12)
fcm <-c(0.47,0.53,0.45,0.39,0.40,0.47,0.48)
gk <-c(0.45,0.51,0.34,0.40,0.42,0.42,0.44)
data4 <- rbind(fcm,gk)
colnames(data4) <- c(6,7,8,9,10,11,12)
# Remove x-axis title from first three plots
# Add las=1 to all plots, so y-axis labels will be rotated
barplot(as.matrix(data1),ylim=c(0,15),main="P wave",
ylab="traveltime rms(ms)", las=1,
col=c("red", "black", "green"), beside=TRUE)
barplot(as.matrix(data2),ylim=c(0,3),main="MT",
ylab="MT functions", las=1,
col=c("red", "black", "green"), beside=TRUE)
barplot(as.matrix(data3),ylim=c(0,13),main="XBI",
ylab="index value", las=1,
col=c("red", "black", "green"), beside=TRUE)
# Change bottom margin for last plot so x-axis title will be included
par(mar=c(4,2.5,3.5,2))
barplot(as.matrix(data4),ylim=c(0,0.6),main="NCE",
xlab="number of clusters", ylab="index value", las=1,
col=c("red", "black"), beside=TRUE)
par(mai=c(0,0,0,0))
plot.new()
legend(legend = c("fcm","gk","gg"), fill = c( "red", "black", "green"),
"center", horiz=TRUE)
I can't post comment, so I've decided to add it as answer...
Let's try with las and cex parameters:
barplot(as.matrix(data1),ylim=c(0,15),main="P wave",
xlab="number of clusters", ylab="traveltime rms(ms)",
col=c("red", "black", "green"), beside=TRUE, las=1, cex.axis=.9)
You can also enlarge bars area by reducing first and third element of mar paratemer.

Tweaking xlabel and ylabel in parallel plot parcoord of R

I made 13 parallel coordinate plots lines, where each plot has x lines, each of 5 points. There are three things that I would like to change:
I would like to remove very long vertical x-axis ticks that protrude below out of the graph
I would like to change the x-axis labels of each plot to be "N", "1", "2", "3", "4"
I would like the y-axis to be labelled for each plot. It currently is not. The maximum y-value for each plot is max(input). So, I like four y-axis labels: max(input), 3/4 max(input), 1/2 max(input), and 1/4 max(input) (all to the nearest integer to keep it neat).
I would like a main title over all the graphs (I'll just call it "Main Title" for now)
Here is my code currently:
par(mfrow = c(3,5))
par(mar=c(0.1,0.1,0.1,0.1))
# For each color (cluster) in the random network
for (i in 1:max(net$colors)){
color = mergedColors[which(net$colors == i)[1]]
input = countTable[which(net$colors==i),]
parcoord(input, lty = 1, var.label = FALSE, col = color)
}
where the str(input) is a data.frame of x observations of 5 variables.
I tried to add things like x.label = c("N","1","2","3","4"), but that did not work.
Edit:
Here is some sample data, as per suggestions. Please let me know if I should include anything else:
net <- data.frame(colors=as.numeric(sample(1:15, 100, replace = T)))
mycols <- c("brown", "blue", "turquoise", "greenyellow", "red",
"pink", "green", "yellow", "magenta", "black","purple",
"tomato1","peachpuff","orchid","slategrey")
mergedColors = mycols[net$colors]
countTable <- data.frame(matrix(sample(1:100,100*5, replace=T),
ncol=5, dimnames=list(NULL, c("Norm","One","Two","Three","Four"))))
OK. I'm not sure I understand request 1, but here's what I came up with so far
library(MASS)
opar<-par(no.readonly=T)
par(mfrow = c(3,5))
par(oma=c(1.2,2,2,0))
par(mar=c(2,2,0.1,0.1))
# For each color (cluster) in the random network
for (i in 1:max(net$colors)){
color = mergedColors[which(net$colors == i)]
input = countTable[which(net$colors==i),]
colnames(input)<-c("N",1:4)
parcoord(input, lty = 1, var.label = FALSE, col = color)
axis(2,at=seq(0,1,length.out=5),labels=seq(min(input),max(input), length.out=5))
}
mtext("Main Title",3, outer=T)
par(opar)

Resources