GGPlot geom_text coloring with facets - r

Hopefully someone here will be able to help me with a problem that I'm having with a ggplot script I'm trying to get right. The script will be used many times with different data, so it needs to be relatively flexible. I've got it almost where I want it, but I've come across a problem I haven't been able to solve.
The script is for a line graph with labels for each line in the right hand margin. Sometimes the graph is faceted, other times it is not.
The piece I'm having trouble with is that I would like to color code the labels in the right margin as black if there was no significant change over time, green if there was positive change, and red if there was negative change. I've got a script that works to carry this out when I only have a single facet, but as soon as I have multiple facets in the graph, the color coding of the labels gives the following error
Error: Incompatible lengths for set aesthetics:
Below is the script with data with multiple facets. The problem seems to be in the way that I'm specifying color in the geom_text line. If I delete the color call in the geom_text line in the script, then I get the attributes printed in the correct place, just not colored. I'm really at a loss on this one. This is my first post here, so let me know if I've done anything wrong with my post.
WITH MULTIPLE FACETS (DOES NOT WORK)
require(ggplot2)
require(grid)
require(zoo)
require(reshape)
require(reshape2)
require(directlabels)
time.data<-structure(list(Attribute = structure(c(1L, 1L, 2L, 2L, 3L, 3L,
4L, 4L, 5L, 5L, 6L, 6L), .Label = c("Taste 1", "Taste 2", "Taste 3",
"Use 1", "Use 2", "Use 3"), class = "factor"), Attribute.Category = structure(c(2L,
2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("Nutritional/Usage",
"Taste/Quality"), class = "factor"), Attribute.Order = c(1L,
1L, 2L, 2L, 3L, 3L, 4L, 4L, 5L, 5L, 6L, 6L), Category.Order = c(1L,
1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L), Color = structure(c(1L,
1L, 2L, 2L, 3L, 3L, 4L, 4L, 5L, 5L, 6L, 6L), .Label = c("#084594",
"#2171B5", "#4292C6", "#6A51A3", "#807DBA", "#9E9AC8"), class = "factor"),
value = c(75L, 78L, 90L, 95L, 82L, 80L, 43L, 40L, 25L, 31L,
84L, 84L), Date2 = structure(c(2L, 1L, 2L, 1L, 2L, 1L, 2L,
1L, 2L, 1L, 2L, 1L), .Label = c("1/1/2013", "9/1/2012"), class = "factor")), .Names = c("Attribute",
"Attribute.Category", "Attribute.Order", "Category.Order", "Color",
"value", "Date2"), class = "data.frame", row.names = c(NA, -12L
))
label.data<-structure(list(7:12, Attribute = structure(1:6, .Label = c("Taste 1",
"Taste 2", "Taste 3", "Use 1", "Use 2", "Use 3"), class = "factor"),
Attribute.Category = structure(c(2L, 2L, 2L, 1L, 1L, 1L), .Label = c("Nutritional/Usage",
"Taste/Quality"), class = "factor"), Attribute.Order = 1:6,
Category.Order = c(1L, 1L, 1L, 2L, 2L, 2L), Color = structure(1:6, .Label = c("#084594",
"#2171B5", "#4292C6", "#6A51A3", "#807DBA", "#9E9AC8"), class = "factor"),
Significance = structure(c(2L, 3L, 1L, 1L, 3L, 2L), .Label = c("neg",
"neu", "pos"), class = "factor"), variable = structure(c(1L,
1L, 1L, 1L, 1L, 1L), .Label = "1/1/2013", class = "factor"),
value = c(78L, 95L, 80L, 40L, 31L, 84L), Date2 = structure(c(1L,
1L, 1L, 1L, 1L, 1L), .Label = "2013-01-01", class = "factor"),
label.color = structure(c(1L, 2L, 3L, 3L, 2L, 1L), .Label = c("black",
"forestgreen", "red"), class = "factor")), .Names = c("",
"Attribute", "Attribute.Category", "Attribute.Order", "Category.Order",
"Color", "Significance", "variable", "value", "Date2", "label.color"
), class = "data.frame", row.names = c(NA, -6L))
color.palette<-as.character(unique(time.data$Color))
time.data$Date2<-as.Date(time.data$Date2,format="%m/%d/%Y")
plot<-ggplot()+
geom_line(data=time.data,aes(as.numeric(time.data$Date2),time.data$value,group=time.data$Attribute,color=time.data$Color),size=1)+
geom_text(data=label.data,aes(x=Inf, y=label.data$value, label=paste(" ",label.data$Attribute)),
color=label.data$label.color,
size=4,vjust=0, hjust=0,na.rm=T)+
facet_grid(Attribute.Category~.,space="free")+
theme_bw()+
scale_x_continuous(breaks=as.numeric(unique(time.data$Date2)),labels=format(unique(time.data$Date2),format = "%b %Y"))+
theme(strip.background=element_blank(),
strip.text.y=element_blank(),
legend.text=element_blank(),
legend.title=element_blank(),
plot.margin=unit(c(1,5,1,1),"cm"),
legend.position="none")+
scale_colour_manual(values=color.palette)
gt3 <- ggplot_gtable(ggplot_build(plot))
gt3$layout$clip[gt3$layout$name == "panel"] <- "off"
grid.draw(gt3)

Some problems:
Inside your aesthetic declarations, you should not be referencing the data columns as time.data$Date2, but just as Date2. The data argument specifies where to look for that information (which needs to all be in the same data.frame for a given layer, but, as you take advantage of, can vary layer to layer).
In the geom_text call, color was not inside the aes call; if you are mapping it to data which is in the data.frame, you have to have it inside the aes call. This would throw a different error after fixing the first part because then it would not be able to find label.color anywhere because it would not know to look inside label.data.
Fixing those, then the scale_colour_manual complains that there are 9 colors and you have only supplied 6. That is because there are 6 colors from the lines and 3 from the text. Since you specified these as actual color names, you can just use scale_colour_identity.
Putting this all together:
plot <- ggplot()+
geom_line(data=time.data, aes(as.numeric(Date2), value,
group=Attribute, color=Color),
size=1)+
geom_text(data=label.data, aes(x=Inf, y=value,
label=paste(" ",Attribute),
color=label.color),
size=4,vjust=0, hjust=0)+
facet_grid(Attribute.Category~.,space="free") +
scale_x_continuous(breaks=as.numeric(unique(time.data$Date2)),
labels=format(unique(time.data$Date2),format = "%b %Y")) +
scale_colour_identity() +
theme_bw()+
theme(strip.background=element_blank(),
strip.text.y=element_blank(),
legend.text=element_blank(),
legend.title=element_blank(),
plot.margin=unit(c(1,5,1,1),"cm"),
legend.position="none")
gt3 <- ggplot_gtable(ggplot_build(plot))
gt3$layout$clip[gt3$layout$name == "panel"] <- "off"
grid.draw(gt3)
To get an idea how much you can strip down your example, this is much closer to minimal:
time.data <-
structure(list(Attribute = structure(c(1L, 1L, 2L, 2L, 3L, 3L,
4L, 4L), .Label = c("Taste 1", "Taste 2", "Use 1", "Use 2"), class = "factor"),
Attribute.Category = structure(c(2L, 2L, 2L, 2L, 1L, 1L,
1L, 1L), .Label = c("Nutritional/Usage", "Taste/Quality"), class = "factor"),
Color = c("#084594", "#084594", "#2171B5", "#2171B5", "#6A51A3",
"#6A51A3", "#807DBA", "#807DBA"), value = c(75L, 78L, 90L,
95L, 43L, 40L, 25L, 31L), Date2 = structure(c(15584, 15706,
15584, 15706, 15584, 15706, 15584, 15706), class = "Date")), .Names = c("Attribute",
"Attribute.Category", "Color", "value", "Date2"), row.names = c(NA,
-8L), class = "data.frame")
label.data <-
structure(list(value = c(78L, 95L, 40L, 31L), Attribute = structure(1:4, .Label = c("Taste 1",
"Taste 2", "Use 1", "Use 2"), class = "factor"), label.color = c("black",
"forestgreen", "red", "forestgreen"), Attribute.Category = structure(c(2L,
2L, 1L, 1L), .Label = c("Nutritional/Usage", "Taste/Quality"), class = "factor"),
Date2 = structure(c(15706, 15706, 15706, 15706), class = "Date")), .Names = c("value",
"Attribute", "label.color", "Attribute.Category", "Date2"), row.names = c(NA,
-4L), class = "data.frame")
ggplot() +
geom_line(data = time.data,
aes(x=Date2, y=value, group=Attribute, colour=Color)) +
geom_text(data = label.data,
aes(x=Date2, y=value, label=Attribute, colour=label.color),
hjust = 1) +
facet_grid(Attribute.Category~.) +
scale_colour_identity()
The theme stuff (and the making the labels visible outside the plot) isn't relevant to the question, nor is the x-axis conversions from Date to numeric to handle having Inf. I also trimmed the data to just the needed columns, and reduced categorical variable to only two categories.

Related

creating a factor-based in dendrogram with R and ggplot2

This is not so much a coding as general approach call for help ;-) I prepared a table containing taxonomic information about organisms. But I want to use the "names" of these organisms, so no values or anything where you could compute a distance or clustering with (this is also all the information I have). I just want to use these factors to create a plot that shows the relationship. My data looks like this:
test2<-structure(list(genus = structure(c(4L, 2L, 7L, 8L, 6L, 1L, 3L,
5L, 5L), .Label = c("Aminobacter", "Bradyrhizobium", "Hoeflea",
"Hyphomonas", "Mesorhizobium", "Methylosinus", "Ochrobactrum",
"uncultured"), class = "factor"), family = structure(c(4L, 1L,
2L, 3L, 5L, 6L, 6L, 6L, 6L), .Label = c("Bradyrhizobiaceae",
"Brucellaceae", "Hyphomicrobiaceae", "Hyphomonadaceae", "Methylocystaceae",
"Phyllobacteriaceae"), class = "factor"), order = structure(c(1L,
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("Caulobacterales",
"Rhizobiales"), class = "factor"), class = structure(c(1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "Alphaproteobacteria", class = "factor"),
phylum = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "Proteobacteria", class = "factor")), .Names = c("genus",
"family", "order", "class", "phylum"), class = "data.frame", row.names = c(NA,
9L))
is it necessary to set up artificial values to describe a distance between the levels?
Here is an attempt using data.tree library
First create a string variable in the form:
Proteobacteria/Alphaproteobacteria/Caulobacterales/Hyphomonadaceae/Hyphomonas
library(data.tree)
test2$pathString <- with(test2,
paste(phylum,
class,
order,
family,
genus, sep = "/"))
tree_test2 = as.Node(test2)
plot(tree_test2)
many things can be done after like:
Interactive network:
library(networkD3)
test2_Network <- ToDataFrameNetwork(tree_test2, "name")
simpleNetwork(test2_Network)
or graph styled
library(igraph)
plot(as.igraph(tree_test2, directed = TRUE, direction = "climb"))
check out the vignette
using ggplot2:
library(ggraph)
graph = as.igraph(tree_test2, directed = TRUE, direction = "climb")
ggraph(graph, layout = 'kk') +
geom_node_text(aes(label = name))+
geom_edge_link(arrow = arrow(type = "closed", ends = "first",
length = unit(0.20, "inches"),
angle = 15)) +
geom_node_point() +
theme_graph()+
coord_cartesian(xlim = c(-3,3), expand = TRUE)
or perhaps:
ggraph(graph, layout = 'kk') +
geom_node_text(aes(label = name), repel = T)+
geom_edge_link(angle_calc = 'along',
end_cap = circle(3, 'mm'))+
geom_node_point(size = 5) +
theme_graph()+
coord_cartesian(xlim = c(-3,3), expand = TRUE)

How to generate facetted ggplot graph where each facet has ordered data?

I want to sort my factors (Condition, Parameter and SubjectID) by MeanWeight and plot MeanWeight against SubjectID such that when faceted by Condition and Parameter, MeanWeight appears in descending order.
Here is my solution, which isn't giving me what I want:
dataSummary <- structure(list(SubjectID = structure(c(1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L), .Label = c("s001",
"s002", "s003", "s004"), class = "factor"), Condition = structure(c(1L,
1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L), .Label = c("1", "2", "3"), class = "factor"), Parameter = structure(c(1L,
2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L,
3L), .Label = c("(Intercept)", "PrevCorr1", "PrevFail1"), class = "factor"),
MeanWeight = c(-0.389685536725783, 0.200987679398502, -0.808114314421089,
-0.10196105040707, 0.0274188815763494, 0.359978984195839,
-0.554583879312783, 0.643791202050396, -0.145042221940287,
-0.0144598460145723, -0.225804028997856, -0.928152539784374,
0.134025102103562, -0.267448309989731, -1.19980109795115,
0.0587152632631923, 0.0050656268880826, -0.156537446664213
)), .Names = c("SubjectID", "Condition", "Parameter", "MeanWeight"
), row.names = c(NA, 18L), class = "data.frame")
## Order by three variables
orderWeights <- order(dataSummary$Condition, dataSummary$Parameter, dataSummary$SubjectID, -dataSummary$MeanWeight)
## Set factors to the new order. I expect this to sort for each facet when plotting, but it doesn't seem to work.
conditionOrder <- dataSummary$Condition[orderWeights]
dataSummary$Condition <- factor(dataSummary$Condition, levels=conditionOrder)
paramOrder <- dataSummary$Parameter[orderWeights]
dataSummary$Parameter <- factor(dataSummary$Parameter, levels=paramOrder)
sbjOrder <- dataSummary$SubjectID[orderWeights]
dataSummary$SubjectID <- factor(dataSummary$SubjectID, levels=sbjOrder)
## Plot
ggplot(dataSummary, aes(x=MeanWeight, y=SubjectID)) +
scale_x_continuous(limits=c(-3, 3)) +
geom_vline(yintercept = 0.0, size = 0.1, colour = "#a9a9a9", linetype = "solid") +
geom_segment(aes(yend=SubjectID), xend=0, colour="grey50") +
geom_point(size=2) +
facet_grid(Parameter~Condition, scales="free_y")
I tried a few other approaches, but they didn't work either:
dataSummary <- dataSummary[order(dataSummary$Condition, dataSummary$Parameter, dataSummary$SubjectID, -dataSummary$MeanWeight),]
or this one
dataSummary <- transform(dataSummary, SubjectID=reorder(Condition, Parameter, SubjectID, MeanWeight))
You can order your data and plot it. However, the labels no longer correspond to Subject ID's, but to the reordered subjects. If that is not what you want, you cannot use faceting but have to plot the parts separately and use e.g.grid.arrangeto combind the different plots.
require(plyr)
## Ordered data
datOrder <- ddply(dataSummary, c("Condition", "Parameter"), function(x){
if (nrow(x)<=1) return(x)
x$MeanWeight <- x$MeanWeight[order(x$MeanWeight)]
x
})
## Plot
ggplot(datOrder, aes(x=MeanWeight, y=SubjectID)) +
scale_x_continuous(limits=c(-3, 3)) +
geom_vline(yintercept = 0.0, size = 0.1, colour = "#a9a9a9", linetype = "solid") +
geom_segment(aes(yend=SubjectID), xend=0, colour="grey50") +
geom_point(size=2) +
facet_grid(Parameter~Condition) +
scale_y_discrete(name="Ordered subjects")

scatterplot regression line lty command is not being recognized

Ive been using the scatterplot command from the Car package to create a plot of my data and I am trying to refine the image for publication. Thus it needs to be in black and white which means I need to change the colored lines to a solid and dashed line. I thought that lty would be the proper command to do this. Within the help of scatterplot, it has a function called by.groups and I think that this is somehow interfering with the lty = c(1,2) or lty = 1:2 idea that I used with the legend part of the code. I don't know how to do this in ggplot so suggestions there would be appreciated if people are so inclined.
here's some example data:
structure(list(ID = structure(c(1L, 1L, 1L, 1L, 1L, 32L, 33L,
33L, 34L, 34L, 34L), .Label = c("F07001", "F07002", "F07003",
"F07004", "F07005", "F07006", "F07008", "F07009", "F07010", "F07011",
"F07014", "F07015", "F07017", "F07018", "F07019", "F07020", "F07021",
"F07022", "F07023", "F07024", "F10001", "F10004", "F10008", "F10009",
"F10010", "F10012", "F10013", "F98015", "M07007", "M07012", "M07013",
"M07016", "M10007", "M10011", "M10015"), class = "factor"), Season = structure(c(1L,
1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L), .Label = c("SUM", "WIN"
), class = "factor"), Time = structure(c(1L, 2L, 1L, 2L, 1L,
2L, 1L, 2L, 1L, 2L, 1L), .Label = c("day", "night"), class = "factor"),
Repro = structure(c(2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L,
3L), .Label = c("f", "fc", "m"), class = "factor"), Comp1 = c(-0.524557195,
-0.794214153, -0.408247216, -0.621285004, -0.238828585, 0.976634392,
-0.202405922, -0.633821539, -0.306163898, -0.302261589, 1.218779672
), ln1wr = c(0.833126490613386, 0.824526258616325, 0.990730077688989,
0.981816265754353, 0.933462450382474, 1.446048015519, 1.13253050687157,
1.1349442179155, 1.14965388471562, 1.14879830358128, 1.14055365645628
)), .Names = c("ID", "Season", "Time", "Repro", "Comp1",
"ln1wr"), row.names = c(1L, 2L, 3L, 4L, 5L, 220L, 221L, 222L,
223L, 224L, 225L), class = "data.frame")
This is the code Ive written thus far:
par(bty="l",las=1)
scatterplot(Comp1~ln1wr|Season, moose,
xlab = "Wolf risk", ylab = "Principal component 1",
labels= row.names(moose),
by.groups=TRUE, smooth=FALSE, boxplots=FALSE,
grid=FALSE, lty = 1:2,
legend.plot=FALSE)
legend("bottomright", title="Season",
legend=levels(moose$Season), bty="n",
pch=1:2, col=1:2, lty=c(1,2))
Here is something in lattice:
xyplot(Comp1~ln1wr,
data=moose,
groups=Season,
xlab = "Wolf risk", ylab = "Principal component 1",
par.settings=list(superpose.symbol=list(pch=1:2, col=1),
superpose.line=list(lty=1:2, col=1)),
panel = function(x, y, ...) {
panel.superpose(x, y, ...,
panel.groups = function(x,y, col, col.symbol, lty, ...) {
panel.xyplot(x, y, col=col.symbol, ...)
panel.abline(lm(y~x), col.line=col.symbol, lty=lty)
}
)
},
auto.key=list(title='Season', space='inside',
#text=c('Summer', 'Winter'),
lines=TRUE)
)
Sorry #BenBolker, I started to work on this before seeing your comment:
Yes, it looks like hacking the scatterplot.default function would be a way to solve this.
Since it's a non-exported function, this is a bit tricky, but here 'tis
# Get function and create copy to edit:
mySP <- car:::scatterplot.default
# Change part of function that plots lines to index lty by i
body(mySP)[[34]][[4]][[4]][[3]][[3]][[3]] <-
quote(reg(reg.line, .x[subs], .y[subs], lty = lty[i], lwd = lwd, log.x = logged("x"),
log.y = logged("y"), col = col[i]))
# Assign altered function back to package namespace
assignInNamespace("scatterplot.default", mySP, "car")
Now your code should yield one solid and one dashed line.

change border from around legend from a scatterplot

This should be simple, but I can't figure out how to remove the border from around my legend. I would also like to place the legend within the graph and remove the inner grid lines and the top and left side border. I am using the scatterplot function and this is the code I've written thus far:
scatterplot(Comp1~ln1wr|Season, moose,
xlab = "Risk", ylab = "Principal component 1",
labels= row.names(moose), by.groups=T, smooth=F, boxplots=F, legend.plot=F)
legend("bottomleft", moose, fill=0)
Here I was just experimenting to even see if I could get the legend to be placed somewhere else, but each time I run this code, I get an error
Error in as.graphicsAnnot(legend) :
argument "legend" is missing, with no default
I would like to place the legend within the graph, but where it will not conflict with the data displaying. here is sample data:
structure(list(ID = structure(c(1L, 1L, 1L, 1L, 1L, 32L, 33L,
33L, 34L, 34L, 34L), .Label = c("F07001", "F07002", "F07003",
"F07004", "F07005", "F07006", "F07008", "F07009", "F07010", "F07011",
"F07014", "F07015", "F07017", "F07018", "F07019", "F07020", "F07021",
"F07022", "F07023", "F07024", "F10001", "F10004", "F10008", "F10009",
"F10010", "F10012", "F10013", "F98015", "M07007", "M07012", "M07013",
"M07016", "M10007", "M10011", "M10015"), class = "factor"), Season = structure(c(1L,
1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L), .Label = c("SUM", "WIN"
), class = "factor"), Time = structure(c(1L, 2L, 1L, 2L, 1L,
2L, 1L, 2L, 1L, 2L, 1L), .Label = c("day", "night"), class = "factor"),
Repro = structure(c(2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L,
3L), .Label = c("f", "fc", "m"), class = "factor"), Comp1 = c(-0.524557195,
-0.794214153, -0.408247216, -0.621285004, -0.238828585, 0.976634392,
-0.202405922, -0.633821539, -0.306163898, -0.302261589, 1.218779672
), ln1wr = c(0.833126490613386, 0.824526258616325, 0.990730077688989,
0.981816265754353, 0.933462450382474, 1.446048015519, 1.13253050687157,
1.1349442179155, 1.14965388471562, 1.14879830358128, 1.14055365645628
)), .Names = c("ID", "Season", "Time", "Repro", "Comp1",
"ln1wr"), row.names = c(1L, 2L, 3L, 4L, 5L, 220L, 221L, 222L,
223L, 224L, 225L), class = "data.frame")
I would suggest
par(bty="l",las=1)
scatterplot(Comp1~ln1wr|Season, moose,
xlab = "Risk", ylab = "Principal component 1",
labels= row.names(moose),
by.groups=TRUE, smooth=FALSE, boxplots=FALSE,
grid=FALSE,
legend.plot=FALSE)
legend("bottomright", title="Season",
legend=levels(moose$Season), bty="n",
pch=1:2, col=1:2)
As indicated in ?legend, bty controls the legend box -- "n" means "none.
I put the legend in the bottom right rather than in the bottom left because it seems to avoid your data better that way.
I used bty="l" to eliminate the top and right box edges (this means "box type L")
I used las=1 to get the y-axis tick labels horizontal -- you didn't ask for that but I strongly prefer it
grid=FALSE removes the internal grid lines
You have to unique your moose ID as you have more than one point for each moose.
legend("bottomleft",legend=unique(moose))
Then you have to associate a color and a point type to your legend (corresponding to your moose ID in your plot). I would also have a look at plot() instead of scatterplot().

Adding error bars to a barchart with multiple groups

I have the following barchart to which I want to add error bars.
library(lattice)
barchart(Change~fTreat,groups=Process,change,
auto.key=list(points=FALSE,rectangles=TRUE),
panel=function(x, y,...){
panel.barchart(x,y,origin = 0,...);
panel.abline(h=0,col="black",...);
}
)
I have tried using the panel.errbars from the memisc package which works great for xyplots, but when I add it to my code it does not respect the groups.
library(memisc)
barchart(cbind(Change,lower,upper)~fTreat,groups=Process,change,
ylab="Pocertage change",
ylim=-115:50,
scales=list(alternating=FALSE,
tick.number=7,
tck=c(-1,0)),
panel=function(x, y,groups,...){
panel.barchart(x,y=change$Change,groups=change$Process,origin = 0,...);
panel.abline(h=0,col="black",...);
panel.errbars(x,y,make.grid="none",ewidth=0.2,type="n",...)
}
)
Any ideas of how to add error bars to my plot either using the panel.errbars or any other function?
The data:
structure(list(Treat = structure(c(3L, 4L, 1L, 2L, 3L, 4L, 1L,
2L), .Label = c("12-380", "12-750", "8-380", "8-750"), class = "factor"),
Process = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c("Resp",
"Cal"), class = c("ordered", "factor")), Change = c(-33.05,
-34.74, 20.94, 18.06, 6.85, -28.57, -8.1, -78.72), upper = c(-13.22896628,
-28.61149669, 31.29930461, 27.30173776, 39.73271282, 9.458372948,
13.11035572, -47.03745704), lower = c(-52.86120694, -40.87446411,
10.57421563, 8.822042178, -26.03144161, -66.60447035, -29.30563327,
-110.3973761), fTreat = structure(c(1L, 2L, 3L, 4L, 1L, 2L,
3L, 4L), .Label = c("8-380", "8-750", "12-380", "12-750"), class = c("ordered",
"factor"))), .Names = c("Treat", "Process", "Change", "upper",
"lower", "fTreat"), row.names = c(NA, -8L), class = "data.frame")
Cheers
Here is another answer I was given using lattice.
prepanel=function(y, stderr, subscripts=subscripts, ...){
uy <- as.numeric(y+stderr[subscripts])
ly <- as.numeric(y-stderr[subscripts])
list(ylim=range(y,uy,ly, finite=TRUE))
}
panel.err=function(x, y, subscripts, groups, stderr, box.ratio, ...){
d <- 1/(nlevels(groups)+nlevels(groups)/box.ratio)
g <- (as.numeric(groups[subscripts])-1); g <- (g-median(g))*d
panel.arrows(as.numeric(x)+g,y-stderr[subscripts], as.numeric(x)+g, y+stderr[subscripts],
code=3,angle=90, length=0.025)
}
barchart(Change~fTreat,groups=Process,change,
stderr=change$stderr,
ylab="Pocertage change",
xlab="Treatment",
ylim=-115:50,
auto.key=list(points=FALSE,rectangles=TRUE,columns=2),
scales=list(alternating=FALSE,
tick.number=7,
tck=c(-1,0)),
prepanel=prepanel,
panel=function(x, y, subscripts, groups, stderr, box.ratio, ...){
panel.barchart(x, y, subscripts=subscripts,
groups=groups, box.ratio=box.ratio,origin=0, ...)
panel.abline(h=0,col="black",...)
panel.err(x, y, subscripts=subscripts,
groups=groups, box.ratio=box.ratio,stderr=change$stderr)
}
)
A big thank you to Walmes Marques Zeviani for providing the code
Here is the modified data:
change <- structure(list(Treat = structure(c(3L, 4L, 1L, 2L, 3L, 4L, 1L,
2L), .Label = c("12-380", "12-750", "8-380", "8-750"), class = "factor"),
Process = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c("Respiration",
"Calcification"), class = c("ordered", "factor")), Change = c(-33L,
-35L, 21L, 18L, 7L, -29L, -8L, -79L), stderr = c(20L, 6L,
10L, 9L, 33L, 38L, 21L, 32L), fTreat = structure(c(1L, 2L,
3L, 4L, 1L, 2L, 3L, 4L), .Label = c("8-380", "8-750", "12-380",
"12-750"), class = c("ordered", "factor"))), .Names = c("Treat",
"Process", "Change", "stderr", "fTreat"), row.names = c(NA, -8L
), class = "data.frame")
This is not what you're asking for, but the plot is rather easy to make with ggplot2 (in a case that this is an option)
dt <- structure(list(Treat = structure(c(3L, 4L, 1L, 2L, 3L, 4L, 1L,
2L), .Label = c("12-380", "12-750", "8-380", "8-750"), class = "factor"),
Process = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c("Resp",
"Cal"), class = c("ordered", "factor")), Change = c(-33.05,
-34.74, 20.94, 18.06, 6.85, -28.57, -8.1, -78.72), upper = c(-13.22896628,
-28.61149669, 31.29930461, 27.30173776, 39.73271282, 9.458372948,
13.11035572, -47.03745704), lower = c(-52.86120694, -40.87446411,
10.57421563, 8.822042178, -26.03144161, -66.60447035, -29.30563327,
-110.3973761), fTreat = structure(c(1L, 2L, 3L, 4L, 1L, 2L,
3L, 4L), .Label = c("8-380", "8-750", "12-380", "12-750"), class = c("ordered",
"factor"))), .Names = c("Treat", "Process", "Change", "upper",
"lower", "fTreat"), row.names = c(NA, -8L), class = "data.frame")
a <- ggplot(dt, aes(y = Change, x = Treat, ymax = upper, ymin = lower))
dodge <- position_dodge(width=0.9)
a + geom_bar(aes(fill = Process), position = dodge) +
geom_errorbar(aes(fill = Process), position = dodge, width = 0.2)

Resources