After I have made a constrained PCoA, and plotted the results in a graph, With the following result. However, the text is not nicely positioned at each location. Is there a possibility to modify this?
Code:
p = plot(ord, type="n") #Plot clean graph
with(env, levels(field)) #set the 3 different field levels
with(env, points(ord, display = "sites", col = colvec[field],pch = 19, bg = colvec[field], cex=1))#display sites with field collours
p = text(ord, display = "species", select = c(19, 50, 47, 13, 29, 12, 45), cex=0.8, col = "lightblue4") # add only some selected species
with(env, legend("topright", legend = levels(field), bty = "n",col = colvec, pch = 21, pt.bg = colvec)) #add legenda
plot(dbDRA, col = "black") #plot vectors
plot(dbDRA, p.max = 0.05, col = "red") #make all significant factors red
Related
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)
QUESTION: I am building a triplot for the results of my distance-based RDA in R, library(vegan). I can get a triplot to build, but can't figure out how to make the colours of my sites different based on their location. Code below.
#running the db-RDA
spe.rda.signif=capscale(species~canopy+gmpatch+site+year+Condition(pair), data=env, dist="bray")
#extract % explained by first 2 axes
perc <- round(100*(summary(spe.rda.signif)$cont$importance[2, 1:2]), 2)
#extract scores (coordinates in RDA space)
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)
#These are my location or site names that I want to use to define the colours of my points
site_names <-env$site
site_names
#set up blank plot with scaling, axes, and labels
plot(spe.rda.signif,
scaling = 1,
type = "none",
frame = FALSE,
xlim = c(-1,1),
ylim = c(-1,1),
main = "Triplot db-RDA - scaling 1",
xlab = paste0("db-RDA1 (", perc[1], "%)"),
ylab = paste0("db-RDA2 (", perc[2], "%)")
)
#add points for site scores - these are the ones that I want to be two different colours based on the labels in the original data, i.e., env$site or site_names defined above. I have copied the current state of the graph
points(sc_si,
pch = 21, # set shape (here, circle with a fill colour)
col = "black", # outline colour
bg = "steelblue", # fill colour
cex = 1.2) # size
Current graph
I am able to add species names and arrows for environmental predictors, but am just stuck on how to change the colour of the site points to reflect their location (I have two locations defined in my original data). I can get them labelled with text, but that is messy.
Any help appreciated!
I have tried separating shape or colour of point by site_name, but no luck.
If you only have a few groups (in your case, two), you could make the group a factor (within the plot call). In R, factors are represented as an integer "behind the scenes" - you can represent up to 8 colors in base R using a simple integer:
set.seed(123)
df <- data.frame(xvals = runif(100),
yvals = runif(100),
group = sample(c("A", "B"), 100, replace = TRUE))
plot(df[1:2], pch = 21, bg = as.factor(df$group),
bty = "n", xlim = c(-1, 2), ylim = c(-1, 2))
legend("topright", unique(df$group), pch = 21,
pt.bg = unique(as.factor(df$group)), bty = "n")
If you have more than 8 groups, or if you would like to define your own colors, you can simply create a vector of colors the length of your groups and still use the same factor method, though with a few slight tweaks:
# data with 10 groups
set.seed(123)
df <- data.frame(xvals = runif(100),
yvals = runif(100),
group = sample(LETTERS[1:10], 100, replace = TRUE))
# 10 group colors
ccols <- c("red", "orange", "blue", "steelblue", "maroon",
"purple", "green", "lightgreen", "salmon", "yellow")
plot(df[1:2], pch = 21, bg = ccols[as.factor(df$group)],
bty = "n", xlim = c(-1, 2), ylim = c(-1, 2))
legend("topright", unique(df$group), pch = 21,
pt.bg = ccols[unique(as.factor(df$group))], bty = "n")
For pch just a slight tweak to wrap it in as.numeric:
pchh <- c(21, 22)
ccols <- c("slateblue", "maroon")
plot(df[1:2], pch = pchh[as.numeric(as.factor(df$group))], bg = ccols[as.factor(df$group)],
bty = "n", xlim = c(-1, 2), ylim = c(-1, 2))
legend("topright", unique(df$group),
pch = pchh[unique(as.numeric(as.factor(df$group)))],
pt.bg = ccols[unique(as.factor(df$group))], bty = "n")
I'm trying to run the below code to produce a simple map with data overlayed but I keep having the same issue with the gridline labels, they should read standard long/lat coords but all I'm getting are 1s.
Everything works until the bottom line of code but I've put all in incase there's anything earlier that might be causing the issue.
tern<-read.table("terndatanumbers2.txt",header=TRUE)
tern.coords <- SpatialPoints(data.frame(x=terns$long,y = terns$lat))
plot(tern.coords, pch = 15, cex = 0.5, col = "blue")
world <- rworldmap::getMap(resolution = "high")
e <- raster::extent(-32,-25,36,40)
azores <- as(raster::crop(world, e), "SpatialPolygons")
raster::crs(tern.coords) <- raster::crs(azores)
plot(azores, col = "gray", xlim = c(-32,-25), ylim = c(36, 40))
plot(tern.coords, pch = 15, cex = 0.5, col = "blue",xlim = c(-32,-25), ylim = c(36, 40), add = T)
plot(gridlines(azores), lty = 3, col = "gray", lwd = 0.5,xlim = c(-32,-25), ylim = c(36, 40), add = T)
text(labels(gridlines(azores)))
plot produced
Any help on this would be appreciated. Thanks.
I've produced a simple line plot using base R and want to add data labels to the point. Any idea how to do this in an automated way? Picture of graph produced here
plot(grant$year, grant$grantee, type = "o", xlab = "Year", ylab = "Number of Grantees", pch = 16, col = "dark blue", lwd = 3, cex = 2)
I estimated your data from the linked picture. By adding text(grant$year, grant$grantee, labels = grant$grantee, pos = 3) after your plot gives us labels. pos = 3 puts the labels above the data points.
year <- c(2015,2016,2017,2018,2019,2020)
grantee <- c(50,55,51,30,52,83)
grant <- data.frame(year, grantee)
plot(grant$year, grant$grantee, type = "o", xlab = "Year", ylab = "Number of Grantees", pch = 16, col = "dark blue", lwd = 3, cex = 2)
text(grant$year, grant$grantee, labels = grant$grantee, pos = 3)
Is it possible to obtain the appropriate value of inset automatically so that the left corner of legend will always be just outside of the top right corner of plot?
In the plot below I had to try several values for inset manually. It would be nice to not have to do it manually since I have to make multiple plots.
graphics.off()
windows(width = 5, height = 5)
set.seed(42)
par(mar = c(5,5,1,10))
plot(rnorm(50,15,5), rnorm(50,15,3),
xlim = c(0,30), ylim = c(5,25),
pch = 19, col = c("red","blue"))
par(xpd = TRUE)
legend("topright", inset = c(-.80, 0),
pch = 19, col = c("red","blue"),
legend = c("LEGEND 1","Second Legend"))
After the plot call, before adding the legend, use par("usr")* to extract the coordinates of the plotting region.
Then, instead of positioning the legend using a 'keyword' and inset, use x and y with the top-right coordinates of the plotting region obtained from par("usr"). Adjust x with a suitable coefficient.
coord <- par("usr")
legend(x = coord[2] * 1.05, y = coord[4],
pch = 19, col = c("red", "blue"),
legend = c("LEGEND 1", "Second Legend"))
And just for fun, a more convoluted alternative.
After plotting, call legend with position topright, but without plotting it to the device (plot = FALSE), and assign it to an object.
Extract the left x and the top y coordinate of the legend box, and its width (see Value section in ?legend), to be used in x and y in legend:
leg <- legend("topright", pch = 19, col = c("red", "blue"),
legend = c("LEGEND 1", "Second Legend"),
plot = FALSE)
legend(x = (leg$rect$left + leg$rect$w) * 1.05, y = leg$rect$top,
pch = 19, col = c("red", "blue"),
legend = c("LEGEND 1", "Second Legend"))
*From ?par
usr A vector of the form c(x1, x2, y1, y2) giving the extremes of the user coordinates of the plotting region.
The position calculations that are made when inset parameter(s) have been specified, are in fact based on par("usr") (see line 188-199 in the legend code).