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)
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)
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.
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)