Related
I have a dataframe df with 4 unique UID - 1001,1002,1003,1004.
I want to write a user-defined function in R that does the following:
Plots Turbidity against Time for each unique UID. Turbidity values are the ones in the Time_1, Time_2 and Time_3 columns. For example, UID = 1001 will have 4 plots in one graph
Add a legend to each graph such as M-L, F-L, M-R, and F-R (from columns Gen and Type)
Add a title to each graph. For example- UID:1001
Export the graphs as pdf or jpeg or tiff pdf files - 4 graphs per page
# dataset
Gen <- c('M','M','M','M','F','F','F','F','M','M','M','M','F','F','F','F')
Site <- rep('FRX',length(gen))
Type <- c('L','L','L','L','L','L','L','L','R','R','R','R','R','R','R','R')
UID <- c(1001,1002,1003,1004,1001,1002,1003,1004,1001,1002,1003,1004,1001,1002,1003,1004)
Time_1 <- c(100.78,112.34,108.52,139.19,149.02,177.77,79.18,89.10,106.78,102.34,128.52,119.19,129.02,147.77,169.18,170.11)
Time_2 <- c(150.78,162.34,188.53,197.69,208.07,217.76,229.48,139.51,146.87,182.54,189.57,199.97,229.28,247.73,269.91,249.19)
Time_3 <- c(250.78,262.34,288.53,297.69,308.07,317.7,329.81,339.15,346.87,382.54,369.59,399.97,329.28,347.73,369.91,349.19)
df <- data.frame(Gen,Site,Type,UID,Time_1,Time_2,Time_3)
df
My attempt
library(ggplot2)
library(tidyr)
# See below for my thoughts/attempt- I am open to other R libraries and approaches
graphplotter <-function(x){
# 1. Convert from wide to long
data_long <- gather(df, time, turbidity, Time_1:Time_3, factor_key=TRUE)
data_long
#2. plot for each unique UID- 1001 to 1004 and add legend
basic <- ggplot(datalong, aes(time, turbidity, shape=Tree)) + geom_point() + geom_line()
basic + theme(
legend.position = c(.95, .95),
legend.justification = c("right", "top"),
legend.box.just = "right",
legend.margin = margin(6, 6, 6, 6))
#3. add title
print(basic+ labs( title= "UID: 1001, Tubidity against time", y="turbidity", x = "Time in hours"))
#4. export as pdf
pdf("turbdity-time.pdf")
par(mfrow = c(2, 2)) ## set the layout to be 2 by 2
sapply(1:4, function(i) plot(basic[,i]))
dev.off()
}
I want all four graphs to look something like this (ignore the circumference and age, should be turbidity and time).
Thanks
I use facet_wrap
graphplotter <-function(x){
x %>%
gather(., time, turbidity, Time_1:Time_3, factor_key=TRUE) %>%
mutate(label = (paste0(Gen, "-", Type))) %>%
#group_by(UID) %>%
ggplot(aes(color = label)) + geom_point(aes(time, turbidity, shape = label, group = label)) +
geom_line(aes(time, turbidity, group = label)) + facet_wrap(~UID) + theme(
legend.position = c(1, 1),
legend.justification = c("right", "top"),
legend.box.just = "right",
legend.margin = margin(1, 1, 1, 1),
legend.text = element_text(size = 7))
}
graphplotter(df)
I have a function called "my function" which creates a ggplot graph and saves it within the function.
#define a function "add_data" to transpose peak values into summary table
my_function <- function(exp, cond) {
#Read in appropriate experiment number
#Remove first 2 columns
#Rename first column to "mintime" and convert to minutes
#Normalize raw fluorescence values
flowdata <- read_csv(paste0(exp, ".csv"))
title <- cond
flowdata <- flowdata[, -c(1:2)] %>%
rename(mintime = 1) %>%
transform(mintime = mintime / 60)
flowdata[,-1] <- data.frame(lapply(flowdata[,-1], function(X) X/X[1]))
#Exclude values up to 5 minutes
#Determine number of peaks per cell
#Add number of peaks per cell to summary table
flowdata_cut <- flowdata[which(flowdata$mintime>=5),]
peak_info <- lapply(flowdata_cut[,-1], findpeaks, threshold=2)
numberpeak <- unlist(lapply(peak_info, nrow))
summarypeaks <- add_peaks(summarypeaks, numberpeak, title)
#Prepare data for line graph
melted <- melt(flowdata, id.vars="mintime")
#####CREATE GRAPH#####
#Plot graph
ggplot(data=melted, aes(x=mintime, y=value, group=variable)) +
geom_line(show.legend = FALSE) +
scale_x_continuous(limits = c(3, 12), breaks = seq(3, 12, by = 3)) +
labs(y="Fluo-4 fluorescence (F/F0)", x = "Time (min)") +
ggtitle(title) +
theme_bw() +
# remove elements we don't need
theme(panel.grid = element_blank(),
panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black"),
panel.background = element_blank())
#####SAVE GRAPH#####
#Save line graph as .png file
ggsave(filename = paste0(exp, "_Line_Graph.jpg"), width = 8, height = 4)
# Return
return(summarypeaks)
}
When I knit the document, the ggplot graph doesn't show in my HTML output despite these parameters
{r fig.cap="Experiment DATE", results = TRUE, eval = TRUE, echo= FALSE, warning=FALSE, message=FALSE, error=FALSE}
#Add experiment and condition
summarypeaks <- my_function(1284, "CONDITION")
Is there a way for the R Markdown HTML document to display the outputs of plots created within a function?
There's a way of getting the plot to show even without returning it, by using side effects. Specifically, you need to save your ggplot object into some variable, say p, and then tell R to print it using plot(). You don't need to change anything about how your function returns its results, it will just happen as a side effect. See below an updated version of your function:
#define a function "add_data" to transpose peak values into summary table
my_function <- function(exp, cond) {
#Read in appropriate experiment number
#Remove first 2 columns
#Rename first column to "mintime" and convert to minutes
#Normalize raw fluorescence values
flowdata <- read_csv(paste0(exp, ".csv"))
title <- cond
flowdata <- flowdata[, -c(1:2)] %>%
rename(mintime = 1) %>%
transform(mintime = mintime / 60)
flowdata[,-1] <- data.frame(lapply(flowdata[,-1], function(X) X/X[1]))
#Exclude values up to 5 minutes
#Determine number of peaks per cell
#Add number of peaks per cell to summary table
flowdata_cut <- flowdata[which(flowdata$mintime>=5),]
peak_info <- lapply(flowdata_cut[,-1], findpeaks, threshold=2)
numberpeak <- unlist(lapply(peak_info, nrow))
summarypeaks <- add_peaks(summarypeaks, numberpeak, title)
#Prepare data for line graph
melted <- melt(flowdata, id.vars="mintime")
#####CREATE GRAPH#####
#Plot graph
p <- ggplot(data=melted, aes(x=mintime, y=value, group=variable)) +
geom_line(show.legend = FALSE) +
scale_x_continuous(limits = c(3, 12), breaks = seq(3, 12, by = 3)) +
labs(y="Fluo-4 fluorescence (F/F0)", x = "Time (min)") +
ggtitle(title) +
theme_bw() +
# remove elements we don't need
theme(panel.grid = element_blank(),
panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.line = element_line(colour = "black"),
panel.background = element_blank())
plot(p)
#####SAVE GRAPH#####
#Save line graph as .png file
ggsave(filename = paste0(exp, "_Line_Graph.jpg"), width = 8, height = 4)
# Return
return(summarypeaks)
}
Edited below with complete and functioning code:
I am trying to create a timeline similar to the one this code creates from the Timeline package, however, the options are not very flexible. For example, I would like to create space between each bar so they are not touching. Also, I am wondering if there is a way to add the "End_Status" column to the graph so that it it is obvious that the data stops there because the animal died. Any help is greatly appreciated.
Example dataset:
df <- data.frame(id = c(rep(1201, 10), rep(1202, 14), rep(1203, 6), rep(1204, 22)),
date = c(seq(1,5,1), seq(5,7,1), seq(7,8,1), seq(2,5,1), seq(7,9,1), seq(11,17,1), seq(1,8,1), seq(8,12, 1), seq(12,26,1 )),
schedule = as.factor(c(rep(1, 5,), rep(2, 3), rep(3, 6),
rep (1, 3), rep (2, 2), rep(3, 5),
rep(1,8), rep(2, 5), rep(1,3), rep(3, 12))),
status = c(rep("", 9), "Mort", rep("", 41), "Mort"))
Code to get the output table I am interested in:
library("data.table")
library(plyr)
library(dplyr)
df<-as.data.table(df)
z <- df[, unique(id)]
################
value_change_first <- function(x,a) { for(i in 1:length(x[,schedule])) {
ifelse(x[a,schedule] == x[a+1,schedule],
x <- x[-(a+1)],
a <- a+1)}
return(x)
}
value_change_second <- function(x,a) {
for(i in 1:length(x[,schedule])) {
ifelse(x[a,schedule] == x[a+1,schedule],
x <- x[-(a)],
a <- a+1)}
return(x)
}
#################
output_1 <- c()
for(i in 1:length(z)){
ids <- df[df$id==z[i],]
out<-value_change_first(ids,1)
output_1<-as.data.frame(rbind(output_1, out))}
#################
output_2 <- c()
for(i in 1:length(z)){
ids <- df[df$id==z[i],]
out<-value_change_second(ids,1)
output_2<-as.data.frame(rbind(output_2, out))}
################
output_1$End_Date <- output_2$date
output_1$End_Status <- output_2$status
names(output_1)[names(output_1)=="date"] <- "Start_Date"
output <- output_1[c(1:2, 5, 3, 6)]
From here I can use the Timeline Package to get something close to what I want:
require(timeline)
tl <- timeline(output,
label.col=names(output)[4],
text.color= NA,
group.col=names(output)[1],
start.col=names(output)[2],
end.col = names(output)[3])
tl + theme_bw() + theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())
My question is how to build something similar in ggplot. Furthermore, I want to specifically add the "Mort" message at a given date by individual from the output dataframe.
I ended up getting this to work like I want:
### creating a end status column that includes mortalities and failures
output$End_Status_Date<-NA
for(i in 1:nrow(output)){
if(output$End_Status[i] == "Mort"){
output$End_Status_Date[i]=as.character(output$End_Date)[i]
}
}
for(i in 1:nrow(output)){
if(output$End_Status[i] == "Failure"){
output$End_Status_Date[i]=as.character(output$End_Date)[i]
}
}
### data structuring
output$id<-as.factor(output$id)
output$End_Status_Date<-as.numeric(output$End_Status_Date)
output$End_Status[output$End_Status == ""] <- NA
output$End_Status<-as.character(output$End_Status)
output$End_Status<-as.factor(output$End_Status)
library(ggplot2)
g2 <- ggplot() +
geom_segment(data=output, aes(x=Start_Date, xend=End_Date, y=id, yend=id, color=schedule), linetype=1, size=2) +
geom_point(data=subset(output, is.na(End_Status)==FALSE),
mapping=aes(x=End_Status_Date, y=id, shape=End_Status, fill=End_Status), size=4)+
scale_colour_manual(values=c("blue4", "chartreuse4", "darkmagenta"))+
scale_fill_manual(values=c("white", "red"))+
scale_shape_manual(values=c(21,24))+
xlab("Time")+
ylab("Individuals")+
theme_bw() + theme(panel.grid.minor = element_blank(), panel.grid.major = element_blank())
g2
You did most of the work already. The key here is just to use geom_rect and take advantage of your y-axis labels to set the ymin and ymax values.
ggplot(output, aes(xmin = Start_Date, xmax = End_Date,
ymin = as.numeric(id) - 1, ymax = as.numeric(id),
fill = schedule)) +
geom_rect() +
geom_text(aes(x = End_Date, y = id, label = End_Status))
There is a need to plot the result of a unsupervised rectangular SOM model. Additional requirements: 1) draw each node as a pie chart with corresponding observed classes; size of a chart should reflect the number of samples in the node. Default plot.kohonen doesn't suit such a case.
Here is a possible solution. The first function som.prep.df is called from the second 'som.draw', which has only two parameters SOM model and observed classes of training set.
som.prep.df <- function(som.model, obs.classes, scaled) {
require(reshape2)
lev <- factor(wine.classes)
df <- data.frame(cbind(unit=som.model$unit.classif, class=as.integer(lev)))
# create table
df2 <- data.frame(table(df))
df2 <- dcast(df2, unit ~ class, value.var="Freq")
df2$unit <- as.integer(df2$unit)
# calc sum
df2$sum <- rowSums(df2[,-1])
# calc fraction borders of classes in each node
tmp <- data.frame(cbind(X0=rep(0,nrow(df2)),
t(apply(df2[,-1], 1, function(x) {
cumsum(x[1:(length(x)-1)]) / x[length(x)]
}))))
df2 <- cbind(df2, tmp)
df2 <- melt(df2, id.vars=which(!grepl("^\\d$", colnames(df2))))
df2 <- df2[,-ncol(df2)]
# define border for each classs in each node
tmp <- t(apply(df2, 1, function(x) {
c(x[paste0("X", as.character(as.integer(x["variable"])-1))],
x[paste0("X", as.character(x["variable"]))])
}))
tmp <- data.frame(tmp, stringsAsFactors=FALSE)
tmp <- sapply(tmp, as.numeric)
colnames(tmp) <- c("ymin", "ymax")
df2 <- cbind(df2, tmp)
# scale size of pie charts
if (is.logical(scaled)) {
if (scaled) {
df2$xmax <- log2(df2$sum)
} else {
df2$xmax <- df2$sum
}
}
df2 <- df2[,c("unit", "variable", "ymin", "ymax", "xmax")]
colnames(df2) <- c("unit", "class", "ymin", "ymax", "xmax")
# replace classes with original levels names
df2$class <- levels(lev)[df2$class]
return(df2)
}
som.draw <- function(som.model, obs.classes, scaled=FALSE) {
# scaled - make or not a logarithmic scaling of the size of each node
require(ggplot2)
require(grid)
g <- som.model$grid
df <- som.prep.df(som.model, obs.classes, scaled)
df <- cbind(g$pts, df[,-1])
df$class <- factor(df$class)
g <- ggplot(df, aes(fill=class, ymax=ymax, ymin=ymin, xmax=xmax, xmin=0)) +
geom_rect() +
coord_polar(theta="y") +
facet_wrap(x~y, ncol=g$xdim, nrow=g$ydim) +
theme(axis.ticks = element_blank(),
axis.text.y = element_blank(),
axis.text.x = element_blank(),
panel.margin = unit(0, "cm"),
strip.background = element_blank(),
strip.text = element_blank(),
plot.margin = unit(c(0,0,0,0), "cm"),
panel.background = element_blank(),
panel.grid = element_blank())
return(g)
}
Usage example.
require(kohonen)
data(wines)
som.wines <- som(scale(wines), grid = somgrid(5, 5, "rectangular"))
# Non-scaled map
som.draw(som.wines, wine.classes)
# Scaled map
som.draw(som.wines, wine.classes, TRUE)
This function can also be used for the visualization of supervised models as well. But it suits only for rectangular maps. Hope this will help someone.
There are several possible improvements:
Choose a better scaling function than logarithm. Because now nodes with single sample become invisible after scaling.
Add legend to the whole plot which will reflect the size of nodes.
Or add information about nodes population on each chart.
PS. The code isn't very elegant, so any suggestions and improvements are welcome.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I'm running a loop to get, at each sub setting of my data set, a map and apply a given palette (and respective legend) accordingly.
People tend to dislike the use of for() loops and maximize vectorization of their approaches. I don't know the best way to vectorize processes with this particular data set.
In this particular case, I'm handling a relatively large data set (distribution species Atlas) that is particularly complex since different methodologies were used and different options must be passed for each species, considering a particular season, different set of observations, etc.
Species may be present at one season and missed into another (They may be a breeder, a resident or a migrant). Maps should be created for all cases (seasons), empty when absent. Additional data (besides those from field work) may be available and used.
Map Legend must accommodate all variations, besides presenting variable in interest (abundances) in a custom discrete scale.
By running a loop I feel (to my limited expertise) I can more easily retain and control the several needed objects, while stepping into the flux I created to produce the pieces of interest and finally create sets of species distributions maps.
My Problem is that I'm storing each resulting ggplot in a list() object. Each species at each season will be stored in a list. The
issue I'm facing is related to scale_fill_manual when used
inside a loop.
The behavior is strange since I get the maps done but with colors applied only to the last ggplot output. Nonetheless all values still being correctly identified in the legend.
to exemplify:
Packages
if (!require(ggplot2)) install.packages("ggplot2",
repos = "http://cran.r-project.org"); library(ggplot2)
if (!require(grid)) install.packages("grid",
repos = "http://cran.r-project.org"); library(grid)
if (!require(RColorBrewer)) install.packages("RColorBrewer",
repos = "http://cran.r-project.org"); library(RColorBrewer)
if (!require(reshape)) install.packages("reshape",
repos = "http://cran.r-project.org"); library(reshape)
A simple example first
#Create a list of colors to be used with scale_manual
palette.l <- list()
palette.l[[1]] <- c('red', 'blue', 'green')
palette.l[[2]] <- c('pink', 'blue', 'yellow')
# Store each ggplot in a list object
plot.l <- list()
#Loop it
for(i in 1:2){
plot.l[[i]] <- qplot(mpg, wt, data = mtcars, colour = factor(cyl)) +
scale_colour_manual(values = palette.l[[i]])
}
In my session plot.l[1] will be painted with colors from palette.l[2].
My particular case
Functions
Arrange Plots
ArrangeGraph <- function(..., nrow=NULL, ncol=NULL, as.table=FALSE) {
dots <- list(...)
n <- length(dots)
if(is.null(nrow) & is.null(ncol)) { nrow = floor(n/2) ; ncol = ceiling(n/nrow)}
if(is.null(nrow)) { nrow = ceiling(n/ncol)}
if(is.null(ncol)) { ncol = ceiling(n/nrow)}
## NOTE see n2mfrow in grDevices for possible alternative
grid.newpage()
pushViewport(viewport(layout=grid.layout(nrow,ncol)))
ii.p <- 1
for(ii.row in seq(1, nrow)) {
ii.table.row <- ii.row
if(as.table) {ii.table.row <- nrow - ii.table.row + 1}
for(ii.col in seq(1, ncol)) {
ii.table <- ii.p
if(ii.p > n) break
print(dots[[ii.table]], vp=VPortLayout(ii.table.row, ii.col))
ii.p <- ii.p + 1
}
}
}
ViewPort
VPortLayout <- function(x, y) viewport(layout.pos.row=x, layout.pos.col=y)
Species data sets
bd.aves.1 <- structure(list(quad = c("K113", "K114", "K114", "K114", "K114",...
due to limited body character number limit, please download entire code from
https://docs.google.com/open?id=0BxSZDr4eTnb9R09iSndzZjBMS28
Species list
list.esp.1 <- c("Sylv mela", "Saxi rube","Ocea leuc")#
# download from the above link
Some taxonomy and other data
txcon.1 <- structure(list(id = c(156L, 359L, 387L), grupo = c("Aves", "Aves",#
# download from the above link
Seasons
kSeason.1 <- c("Inverno", "Primavera", "Outono")
A Sample Grid
grid500.df.1 <- structure(list(id = c("K113", "K113", "K113", "K113", "K113",#...
# download from the above link
Additional Mapping elements
Shoreline
coastline.df.1 <- structure(list(long = c(182554.963670234, 180518, 178865.39,#...
# download from the above link
Labels placement adjustments
kFacx1 <- c(9000, -13000, -10000, -12000)
The R Code
for(i in listsp.1) { # LOOP 1 - Species
# Set up objects
sist.i <- list() # Sistematic observations
nsist.i <- list() # Non-Sistematic observations
breaks.nind.1 <- list() # Breaks on abundances
## Grid and merged dataframe
spij.1 <- list() # Stores a dataframe for sp i at season j
## Palette build
classes.1 <- list()
cllevels.1 <- list()
palette.nind.1 <- list() # Color palette
## Maps
grid500ij.1 <- list() # Grid for species i at season j
map.dist.ij.1 <- NULL
for(j in 1:length(kSeason.1)) { # LOOP 2 - Seasons
# j assume each season: Inverno, Primavera, Outono
# Sistematic occurences ===================================================
sist.i.tmp <- nrow(subset(bd.aves.1, esp == i & cod_tipo %in% sistematica &
periodo == kSeason.1[j]))
if (sist.i.tmp!= 0) { # There is sistematic entries, Then:
sist.i[[j]]<- ddply(subset(bd.aves.1,
esp == i & cod_tipo %in% sistematica &
periodo == kSeason.1[j]),
.(periodo, quad), summarise, nind = sum(n_ind),
codnid = max(cod_nidi))
} else { # No Sistematic entries, Then:
sist.i[[j]] <- data.frame('quad' = NA, 'periodo' = NA, 'nind' = NA,
'codnid' = NA, stringsAsFactors = F)
}
# Additional Entries (RS1) e other non-sistematic entries (biblio) =======
nsist.tmp.i = nrow(subset(bd.aves.1, esp == i & !cod_tipo %in% sistematica &
periodo == kSeason.1[j]))
if (nsist.tmp.i != 0) { # RS1 and biblio entries, Then:
nsist.i[[j]] <- subset(bd.aves.1,
esp == i & !cod_tipo %in% sistematica &
periodo == kSeason.1[j] &
!quad %in% if (nrow(sist.i[[j]]) != 0) {
subset(sist.i[[j]],
select = quad)$quad
} else NA,
select = c(quad, periodo, cod_tipo, cod_nidi)
)
names(nsist.i[[j]])[4] <- 'codnid'
} else { # No RS1 and biblio entries, Then:
nsist.i[[j]] = data.frame('quad' = NA, 'periodo' = NA, 'cod_tipo' = NA,
'codnid' = NA, stringsAsFactors = F)
}
# Quantile breaks =========================================================
if (!is.na(sist.i[[j]]$nind[1])) {
breaks.nind.1[[j]] <- c(0,
unique(
ceiling(
quantile(unique(
subset(sist.i[[j]], is.na(nind) == F)$nind),
q = seq(0, 1, by = 0.25)))))
} else {
breaks.nind.1[[j]] <- 0
}
# =========================================================================
# Build Species dataframe and merge to grid
# =========================================================================
if (!is.na(sist.i[[j]]$nind[1])) { # There are Sistematic entries, Then:
spij.1[[j]] <- merge(unique(subset(grid500df.1, select = id)),
sist.i[[j]],
by.x = 'id', by.y = 'quad', all.x = T)
# Adjust abundances when equals to NA ===================================
spij.1[[j]]$nind[is.na(spij.1[[j]]$nind) == T] <- 0
# Break abundances to create discrete variable ==========================
spij.1[[j]]$cln <- if (length(breaks.nind.1[[j]]) > 2) {
cut(spij.1[[j]]$nind, breaks = breaks.nind.1[[j]],
include.lowest = T, right = F)
} else {
cut2(spij.1[[j]]$nind, g = 2)
}
# Variable Abundance ====================================================
classes.1[[j]] = nlevels(spij.1[[j]]$cln)
cllevels.1[[j]] = levels(spij.1[[j]]$cln)
# Color Palette for abundances - isolated Zero class (color #FFFFFF) ====
if (length(breaks.nind.1[[j]]) > 2) {
palette.nind.1[[paste(kSeason.1[j])]] = c("#FFFFFF", brewer.pal(length(
cllevels.1[[j]]) - 1, "YlOrRd"))
} else {
palette.nind.1[[paste(kSeason.1[j])]] = c(
"#FFFFFF", brewer.pal(3, "YlOrRd"))[1:classes.1[[j]]]
}
names(palette.nind.1[[paste(kSeason.1[j])]])[1 : length(
palette.nind.1[[paste(kSeason.1[j])]])] <- cllevels.1[[j]]
# Add RS1 and bilbio values to palette ==================================
palette.nind.1[[paste(kSeason.1[j])]][length(
palette.nind.1[[paste(kSeason.1[j])]]) + 1] <- '#CCC5AF'
names(palette.nind.1[[paste(kSeason.1[j])]])[length(
palette.nind.1[[paste(kSeason.1[j])]])] <- 'Suplementar'
palette.nind.1[[paste(kSeason.1[j])]][length(
palette.nind.1[[paste(kSeason.1[j])]]) + 1] <- '#ADCCD7'
names(palette.nind.1[[paste(kSeason.1[j])]])[length(
palette.nind.1[[paste(kSeason.1[j])]])] <- 'Bibliografia'
# Merge species i dataframe to grid map =================================
grid500ij.1[[j]] <- subset(grid500df.1, select = c(id, long, lat, order))
grid500ij.1[[j]]$cln = merge(grid500ij.1[[j]],
spij.1[[j]],
by.x = 'id', by.y = 'id', all.x = T)$cln
# Adjust factor levels of cln variable - Non-Sistematic data ============
levels(grid500ij.1[[j]]$cln) <- c(levels(grid500ij.1[[j]]$cln), 'Suplementar',
'Bibliografia')
if (!is.na(nsist.i[[j]]$quad[1])) {
grid500ij.1[[j]]$cln[grid500ij.1[[j]]$id %in% subset(
nsist.i[[j]], cod_tipo == 'RS1', select = quad)$quad] <- 'Suplementar'
grid500ij.1[[j]]$cln[grid500ij.1[[j]]$id %in% subset(
nsist.i[[j]], cod_tipo == 'biblio', select = quad)$quad] <- 'Bibliografia'
}
} else { # No Sistematic entries, Then:
if (!is.na(nsist.i[[j]]$quad[1])) { # RS1 or Biblio entries, Then:
grid500ij.1[[j]] <- grid500df
grid500ij.1[[j]]$cln <- '0'
grid500ij.1[[j]]$cln <- factor(grid500ij.1[[j]]$cln)
levels(grid500ij.1[[j]]$cln) <- c(levels(grid500ij.1[[j]]$cln),
'Suplementar', 'Bibliografia')
grid500ij.1[[j]]$cln[grid500ij.1[[j]]$id %in% subset(
nsist.i[[j]], cod_tipo == 'RS1',
select = quad)$quad] <- 'Suplementar'
grid500ij.1[[j]]$cln[grid500ij.1[[j]]$id %in% subset(
nsist.i[[j]],cod_tipo == 'biblio',
select = quad)$quad] <- 'Bibliografia'
} else { # No entries, Then:
grid500ij.1[[j]] <- grid500df
grid500ij.1[[j]]$cln <- '0'
grid500ij.1[[j]]$cln <- factor(grid500ij.1[[j]]$cln)
levels(grid500ij.1[[j]]$cln) <- c(levels(grid500ij.1[[j]]$cln),
'Suplementar', 'Bibliografia')
}
} # End of Species dataframe build
# Distribution Map for species i at season j =============================
if (!is.na(sist.i[[j]]$nind[1])) { # There is sistematic entries, Then:
map.dist.ij.1[[paste(kSeason.1[j])]] <- ggplot(grid500ij.1[[j]],
aes(x = long, y = lat)) +
geom_polygon(aes(group = id, fill = cln), colour = 'grey80') +
coord_equal() +
scale_x_continuous(limits = c(100000, 180000)) +
scale_y_continuous(limits = c(-4000, 50000)) +
scale_fill_manual(
name = paste("LEGEND",
'\nSeason: ', kSeason.1[j],
'\n% of Occupied Cells : ',
sprintf("%.1f%%", (length(unique(
grid500ij.1[[j]]$id[grid500ij.1[[j]]$cln != levels(
grid500ij.1[[j]]$cln)[1]]))/12)*100), # percent
sep = ""
),
# Set Limits
limits = names(palette.nind.1[[j]])[2:length(names(palette.nind.1[[j]]))],
values = palette.nind.1[[j]][2:length(names(palette.nind.1[[j]]))],
drop = F) +
opts(
panel.background = theme_rect(),
panel.grid.major = theme_blank(),
panel.grid.minor = theme_blank(),
axis.ticks = theme_blank(),
title = txcon.1$especie[txcon.1$esp == i],
plot.title = theme_text(size = 10, face = 'italic'),
axis.text.x = theme_blank(),
axis.text.y = theme_blank(),
axis.title.x = theme_blank(),
axis.title.y = theme_blank(),
legend.title = theme_text(hjust = 0,size = 10.5),
legend.text = theme_text(hjust = -0.2, size = 10.5)
) +
# Shoreline
geom_path(inherit.aes = F, aes(x = long, y = lat),
data = coastline.df.1, colour = "#997744") +
# Add localities
geom_point(inherit.aes = F, aes(x = x, y = y), colour = 'grey20',
data = localidades, size = 2) +
# Add labels
geom_text(inherit.aes = F, aes(x = x, y = y, label = c('Burgau',
'Sagres')),
colour = "black",
data = data.frame(x = c(142817 + kFacx1[1], 127337 + kFacx1[4]),
y = c(11886, 3962), size = 3))
} else { # NO sistematic entries,then:
map.dist.ij.1[[paste(kSeason.1[j])]] <- ggplot(grid500ij.1[[j]],
aes(x = long, y = lat)) +
geom_polygon(aes.inherit = F, aes(group = id, fill = cln),
colour = 'grey80') +
#scale_color_manual(values = kCorLimiteGrid) +
coord_equal() +
scale_x_continuous(limits = c(100000, 40000)) +
scale_y_continuous(limits = c(-4000, 180000)) +
scale_fill_manual(
name = paste('LEGENDA',
'\nSeason: ', kSeason.1[j],
'\n% of Occupied Cells :',
sprintf("%.1f%%", (length(unique(
grid500ij.1[[j]]$id[grid500ij.1[[j]]$cln != levels(
grid500ij.1[[j]]$cln)[1]]))/12 * 100)), # percent
sep = ''),
limits = names(kPaletaNsis)[2:length(names(kPaletaNsis))],
values = kPaletaNsis[2:length(names(kPaletaNsis))],
drop = F) +
opts(
panel.background = theme_rect(),
panel.grid.major = theme_blank(),
panel.grid.minor = theme_blank(),
title = txcon.1$especie[txcon.1$esp == i],
plot.title = theme_text(size = 10, face = 'italic'),
axis.ticks = theme_blank(),
axis.text.x = theme_blank(),
axis.text.y = theme_blank(),
axis.title.x = theme_blank(),
axis.title.y = theme_blank(),
legend.title = theme_text(hjust = 0,size = 10.5),
legend.text = theme_text(hjust = -0.2, size = 10.5)
) +
# Add Shoreline
geom_path(inherit.aes = F, data = coastline.df.1,
aes(x = long, y = lat),
colour = "#997744") +
# Add Localities
geom_point(inherit.aes = F, aes(x = x, y = y),
colour = 'grey20',
data = localidades, size = 2) +
# Add labels
geom_text(inherit.aes = F, aes(x = x, y = y,
label = c('Burgau', 'Sagres')),
colour = "black",
data = data.frame(x = c(142817 + kFacx1[1],
127337 + kFacx1[4],),
y = c(11886, 3962)),
size = 3)
} # End of Distribution map building for esp i and j seasons
} # Fim do LOOP 2: j Estacoes
# Print Maps
png(file = paste('panel_species',i,'.png', sep = ''), res = 96,
width = 800, height = 800)
ArrangeGraph(map.dist.ij.1[[paste(kSeason.1[3])]],
map.dist.ij.1[[paste(kSeason.1[2])]],
map.dist.ij.1[[paste(kSeason.1[1])]],
ncol = 2, nrow = 2)
dev.off()
graphics.off()
} # End of LOOP 1
map.dist.ij.1[[paste(kSeason.1[3])]] is the only with color palette applied to polygons, but the legend items is well defined for each j map.
Output using R Code
As we see, Legends are OK but not colored.
Hope not missing anything. Sorry for some lost Portuguese terminology.
Honestly, I have not looked much at your code for your specific problem--a bit too much to wade through!--but for your demo example, adding print(plot.l[[i]]) in your loop.
#Create a list of colors to be used with scale_manual
palette.l <- list()
palette.l[[1]] <- c('red', 'blue', 'green')
palette.l[[2]] <- c('pink', 'blue', 'yellow')
# Store each ggplot in a list object
plot.l <- list()
# Loop it
for(i in 1:2) {
plot.l[[i]] <- qplot(mpg, wt, data = mtcars, colour = factor(cyl)) +
scale_colour_manual(values = palette.l[[i]])
print(plot.l[[i]]) ### Added to your loop
}
In the case of your minimal example, though, this also works (without first having to create an empty list to store your plots) and I think it at least looks a lot cleaner. I'm not sure if something similar can be adapted to suit your larger scenario.
#Create a list of colors to be used with scale_manual
palette.l <- list(c('red', 'blue', 'green'),
c('pink', 'blue', 'yellow'))
p <- qplot(mpg, wt, data = mtcars, colour = factor(cyl))
# Use lapply and "force" to get your plots in a list
plot.l <- lapply(palette.l,
function(x) {
force(x)
p + scale_color_manual(values = x)
})