I get a problem for setting the position of legend and wonder if anyone can help.
I follow this example:
http://www.thisisthegreenroom.com/2009/choropleths-in-r/
My code is:
require(maps)
require(ggmap)
library(openxlsx)
rm(list = ls())
map("state", "Arizona")
setwd('M:/SCC/Q-Board')
PM25 <- read.xlsx("PM2.5_Emission_AZ_60 EIS emission sectors.xlsx", sheet = 'Emission_County', colNames = TRUE)
colors = c("#F1EEF6", "#D4B9DA", "#C994C7", "#DF65B0", "#DD1C77",
"#980043")
PM25$colorBuckets <- as.numeric(cut(PM25$PM25, c(0, 5, 10, 20, 30,40, 50)))
map("county",'Arizona', col = colors[PM25$colorBuckets], fill = TRUE,boundary = TRUE, resolution = 0,
lty = 1, projection = "polyconic")
title("PM2.5 Emission by county, 2011")
leg.txt <- c("<5", "5-10", "10-20", "20-30", "30-40", ">40")
legend("bottom", leg.txt, horiz = F, fill = colors,bty="n",title = 'Unit:1000 tons')
Then, the output figure was shown in below. I try to change the position by setting "top", "left"....
But the legend are still overlap with the figure.
Thank you for your help !
It seems to me that you simply run of out the plotting region. This is very common for spatial plot, which will often occupy a significant amount of your plotting domain. I would split the domain into two: one for spatial plot, the other for legend. The following code does this:
## a function to set up plotting region
## l: ratio of left region
## r: ratio of right region
split.region <- function(l, r) {
layout(matrix(c(rep(1, l), rep(2, r)), nrow = 1))
mai <- par("mai")
mai[2] <- 0.1
mai[4] <- 0
par(mai = mai)
}
# use 80% region for main image
# use 20% region for legend
split.region(4, 1)
## produce your main plot
image(x = 0:10/10, y = 0:10/10, matrix(rbinom(100, 1, 0.3), 10), bty= "n", xaxt = "n", yaxt = "n", ann = FALSE, main = "sample plot")
## set up 2nd plot, with nothing
plot(1:2, bty="n", ann=FALSE, xaxt = "n", yaxt = "n", col = "white")
## add your legend to your second plot
leg.txt <- c("<5", "5-10", "10-20", "20-30", "30-40", ">40")
## place legend at bottom left
legend("bottomleft", leg.txt, horiz = F, pch = 15, col = 1:6, bty="n", title = 'Unit:1000 tons', cex = 1.5)
Adjust l, r until you are satisfied.
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 am designing a sheet with multiple plots, but for all the bar plots with only one bar the x-axis label isn't shown.
How can I make the axis label be shown at all my plots?
Here is my result:
Here is my code:
library(utils)
library(RColorBrewer)
library(readr)
library(readxl)
rm(list=ls())
color <- brewer.pal(6,"Spectral")
overlap <- read_excel("overlap.xlsx")
par(mar=c(3,3,1,1),mgp=c(2,0.9,0),xaxs="i", yaxs="i")
overlap.dat <- overlap[overlap$`Countries and areas`=="Pakistan",]
overlap.dat <- t(overlap.dat)
colnames(overlap.dat) = overlap.dat[5,]
overlap.dat <- as.matrix(overlap.dat[-c(1:8,14),])
barplot(overlap.dat, main = "Pakistan", col = color, ylim = c(0,100), xlim = c(0, 8),
cex.names = 0.8, names.arg = colnames(overlap.dat), legend = TRUE,
args.legend = list(x = "topright", y = 100, cex = 0.8, bty = "n"), las = 2 )
But I have solved it already. The problem was that r changed my matrix to a vector for all the single row dataframes.
Here the code how I solved it:
color <- brewer.pal(6,"Spectral")
overlap <- read_excel("overlap.xlsx")
par(mar=c(3,3,1,1),mgp=c(2,0.9,0),xaxs="i", yaxs="i")
overlap.dat <- overlap[overlap$`Countries and areas`=="Pakistan",]
overlap.dat <-as.data.frame(t(overlap.dat))
overlap.dat <- as.matrix(overlap.dat, drop=FALSE)
overlap.dat <- as.matrix(overlap.dat[-c(1:8,14),], drop=FALSE)
colnames(overlap.dat)= overlap[overlap$`Countries and areas`=="Pakistan",]$Year
barplot(overlap.dat, main = "Pakistan", col =color, ylim=c(0,100), xlim=c(0,8),cex.names=0.8, names.arg = colnames(overlap.dat),
legend=TRUE, args.legend = list(x="topright",y=100, cex=0.8,bty="n"), las=2 )
I'm using base R plot(), and I want a legend (a color block and key) to show up above (outside) the top right of my plot next to my title (generated using title()).
What's the best way to do this?
Maybe something like this is what you're looking for:
x <- c(1,2,3,4)
y <- c(4,1,3,2)
z <- c(1,2,3,4)
dat <- data.frame(x,y,z)
windows(width = 5, height = 9) #quartz() on Mac
layout(matrix(c(1,2), 2, 1, byrow = TRUE), heights=c(0.5,1))
par(oma = c(4,3,0,0) + 0.1, mar = c(0,0,1,1) + 0.1)
plot(dat$x, y=rep(1,4), type = "n", axes = F, ylab = "", xlab = "")
legend(x = "bottomright", legend = c("y", "z"), fill = c("blue", "red"))
plot(dat$x, dat$y, type = "n", main = "PLOT")
lines(z, col = "red")
lines(y, col = "blue")
Basically this makes two plots, one is just invisible and shortened so all that's displayed is the legend.
You may be able to addtionally tweak the margins around the legend and other graphical parameters (?par) to get the layout better.
how to
Combine a bar chart and line in single plot in R (from different data sources)?
Say I have two data sources as:
barData<-c(0.1,0.2,0.3,0.4) #In percentage
lineData<-c(100,22,534,52,900)
Note that they may not be in the same scale.
Can I plot both barData and LineData in one plot and make them good looking ?
I cant use ggplot in this case so this is not a duplicated question..
Something like the following:
Maybe this helps as a starting point:
par(mar = rep(4, 4))
barData<-c(0.1,0.2,0.3,0.4) * 100
y <- lineData<-c(100,22,534,900);
x <- barplot(barData,
axes = FALSE,
col = "blue",
xlab = "",
ylab = "",
ylim = c(0, 100) )[, 1]
axis(1, at = x, labels = c("Julia", "Pat", "Max", "Norman"))
ats <- c(seq(0, 100, 15), 100); axis(4, at = ats, labels = paste0(ats, "%"), las = 2)
axis(3, at = x, labels = NA)
par(new = TRUE)
plot(x = x, y = y, type = "b", col = "red", axes = FALSE, xlab = "", ylab = "")
axis(2, at = c(pretty(lineData), max(lineData)), las = 2)
mtext(text="Lines of code by Programmer", side = 3, line = 1)
box()