How do I remove the _printed_ output warnings using ggplot2 with knitr - r

GGplot2 prints out a warning when using scale_colour_gradient twice in a plot, which I cannot suppress in knitr. Here is a screenshot of my browser after knitting an RHTML file:
I need to colour gradients, one for the line (cheap / dear of yield curve) and one for the instruments which is similar but subtly different (coloured dots).
Here is my ggplot code:
ggp <- ggplot(polys, aes(x = xvals, y = yvals)) +
#geom_polygon(aes(fill = - value, group = id, alpha = value)) + # lovely blue
geom_polygon(aes(fill = value, group = id, alpha = value)) + # lovely shiny light blue middle draw me in
scale_x_log10(breaks = xaxtickpos, minor_breaks = NULL) +
theme(legend.position = "none", panel.background = element_rect(fill = "grey85", colour = NA)) +
xlab("maturity") + ylab("bps")
ggp <- ggp + geom_line(data = quanmelt[quanmelt[, "percentile"] %in% outerthresh, ],
aes(x = mat, y = value, group = percentile), colour = "white", size = 2)
ggp <- ggp + geom_line(data = quanmelt[quanmelt[, "percentile"] %in% innerthresh, ],
aes(x = mat, y = value, group = percentile), colour = "white", size = 1,
linetype = "dotted")
#add last few days line/today (this doesn't work very well hence commented out)
todayback <- todayline[todayline$daysback == 2, ] # get this historic lines
ggp <- ggp + geom_smooth(data = todayback, aes(x = mat, y = value, group = daysback),
colour = "darkred", linetype = "dashed",
se = FALSE, size = 1, method = "loess", span = (ifelse(smooth, 0.3, 0.1)))
#add boxplot
ggp <- ggp + geom_boxplot(data = meltcdlong, aes(x = mat, y = value, group = bond), outlier.size = NA,
colour = "grey30", alpha = 0.5, size = 0.2, width = 0.025)
# add the latest point
ggp <- ggp + geom_point(data = latestcdpoint, aes(x = mat, y = value, group = bond))
# now do labels (twice - one for above, one for below)
ggp <- ggp + geom_text(data = latestcdpoint[latestcdpoint$adjustvertvec == 1, ], aes(x = mat, y = labelposies, label = label),
angle = 90, colour = "grey20", size = 3, hjust = 0, alpha = 0.5)
ggp <- ggp + geom_text(data = latestcdpoint[latestcdpoint$adjustvertvec == 0, ], aes(x = mat, y = labelposies, label = label),
angle = 90, colour = "grey20", size = 3, hjust = 1, alpha = 0.5)
#now print a nice z-score graded colour line for the curve
todaytoday <- todayline[todayline$daysback == 0, ]
minz <- min(rescale(todaytoday[, "zscore"])) # for scaling of z-score line gradient colours
maxz <- max(rescale(todaytoday[, "zscore"]))
bpspline <- smooth.spline(todaytoday$mat, todaytoday$value, spar = 0.4) # Smooth out the curve with lots of points
zscorespline <- smooth.spline(todaytoday$mat, todaytoday$zscore) # and smooth out the zscores too
xplot <- seq(2, maxmat, by = 0.1)
todayplotter <- data.frame(mat = xplot, value = predict(bpspline, xplot)$y,
zscore = rescale(c(-5, 5, predict(zscorespline, xplot)$y))[-1:-2]) # build the plotter
ggp <- ggp + geom_path(data = todayplotter, aes(x = mat, y = value, colour = zscore), size = 2, linejoin = "bevel") +
scale_colour_gradientn(colours = gradientcolours, values = gradientscale, limits = c(minz, maxz))
#and the title
ggp <- ggp + ggtitle(cCode)
# now the test chart
mm <<- meltcdrecent[meltcdrecent$daysback == 0, ]
ggp <- ggp + geom_point(data = mm, aes(x = mat, y = value, colour = rescale(c(-5, 5, zscore))[-1:-2]), size = 6) +
scale_colour_gradientn(colours = gradientcolours, values = gradientscale, limits = c(0, 1))
ggp <- ggp + geom_point(data = mm, aes(x = mat, y = value), colour = "black", size = 4.5)
ggp <- ggp + geom_text(data = mm, aes(x = mat, y = value), label = round(mm$zscore, 1), colour = "white", size = 2, alpha = 0.7)
It's quite complex, but you can see I have two scale_colour_gradient(s).
Here is my knitr code:
<!--begin.rcode changer, echo=FALSE, fig.height=4.5, fig.width=8
for(x in ac) {
g <- ggCD(x, plotit = FALSE)
suppressWarnings(plot(g$cdChart))
}
end.rcode-->
I would like either to get rid of these warnings (they're not actual real warnings, so suppressWarnings doesn't work), or else, use scale_colour_gradient in a way which does not produce this text in the first place.

Change
<!--begin.rcode changer, echo=FALSE, fig.height=4.5, fig.width=8
into
<!--begin.rcode changer, echo=FALSE, fig.height=4.5, fig.width=8, message=FALSE

Related

ggplot geom_rect color gradient (without reference to data)?

I was wondering if it is possible to have a geom_rect with a color gradient without a data reference, i.e. outside of aes().
I would like the two rectangles in the bottom of the following plot to show a color gradient from red to white (left to right) and the top one to show a color gradient from yellow to white.
Is this possible in a simple way or do I have to create data to refer to?
ggplot() +
geom_rect(aes(xmin = c(1, 3), xmax = c(2.5, 4), ymin = c(1, 1), ymax = c(2, 2)), color = "black", fill = "red") +
geom_rect(aes(xmin = 1, xmax = 3.5, ymin = 3, ymax = 4), color = "black", fill = "yellow") +
theme_bw() +
theme(panel.grid = element_blank())
I tried to use scale_fill_gradient with geom_tile but this doesn't really do what I want: 1. the two supposed-to-be-red rectangles share a gradient and don't start with pure red each and 2. I can't manage to use two different scale_fill_gradient's in one plot.
foo <- tibble(x = seq(from = 1, to = 2.5, by = 0.001),
y = rep(1, 1501))
bar <- tibble(x = seq(from = 3, to = 4, by = 0.001),
y = rep(1, 1001))
foobar <- tibble(x = seq(from = 1, to = 3.5, by = 0.001),
y = rep(3, 2501))
ggplot() +
geom_tile(data = foo, aes(x = x, y = y, fill = x)) +
geom_tile(data = bar, aes(x = x, y = y, fill = x)) +
scale_fill_gradient(low = 'red', high = 'white') +
geom_tile(data = foobar, aes(x = x, y = y, fill = x)) +
scale_fill_gradient(low = 'yellow', high = 'white') +
theme_bw() +
theme(panel.grid = element_blank())
You could use the function new_scale_fill from ggnewscale between your two different scale_fill_gradient functions in your plot process. This will reset your aesthetics to make it possible to use another gradient like this:
library(tibble)
foo <- tibble(x = seq(from = 1, to = 2.5, by = 0.001),
y = rep(1, 1501))
bar <- tibble(x = seq(from = 3, to = 4, by = 0.001),
y = rep(1, 1001))
foobar <- tibble(x = seq(from = 1, to = 3.5, by = 0.001),
y = rep(3, 2501))
library(ggplot2)
library(ggnewscale)
ggplot() +
geom_tile(data = foo, aes(x = x, y = y, fill = x)) +
geom_tile(data = bar, aes(x = x, y = y, fill = x)) +
scale_fill_gradient(low = 'red', high = 'white') +
new_scale_fill() +
geom_tile(data = foobar, aes(x = x, y = y, fill = x)) +
scale_fill_gradient(low = 'yellow', high = 'white') +
theme_bw() +
theme(panel.grid = element_blank())
Created on 2022-09-23 with reprex v2.0.2
To add for each geom_tile a gradient color, you could use for each tile new_scale_fill like this:
library(ggplot2)
library(ggnewscale)
ggplot() +
geom_tile(data = foo, aes(x = x, y = y, fill = x)) +
scale_fill_gradient(low = 'red', high = 'white', guide = 'none') +
new_scale_fill() +
geom_tile(data = bar, aes(x = x, y = y, fill = x)) +
scale_fill_gradient(low = 'red', high = 'white') +
new_scale_fill() +
geom_tile(data = foobar, aes(x = x, y = y, fill = x)) +
scale_fill_gradient(low = 'yellow', high = 'white') +
theme_bw() +
theme(panel.grid = element_blank())
Created on 2022-09-23 with reprex v2.0.2

Legend for additional points in a ggplot

Steeling the example of this question (Link), I want to ask if it is possible to add the additional blue point to the legend?
dat <- data.frame(cond = rep(c("A", "B"), each=10),
xvar = 1:20 + rnorm(20,sd=3),
yvar = 1:20 + rnorm(20,sd=3))
g1 <- dat[15,]
ggplot(dat, aes(x = xvar, y = yvar, shape = cond,
colour = cond), size = 2.5) +
geom_point(alpha = 1) +
geom_point(data = g1, colour = "blue", size = 4, show_guide = FALSE)
You can put the aesthetics for the additional points layer inside aes instead of outside to get it added to the legend. You can use any string value; that string will be the name in the legend.
Then you can control the color and shape of that point via scale_*_manual layers.
I additionally changed the size of that point in the legend using override.aes, which is optional.
ggplot(dat, aes(x = xvar, y = yvar, shape = cond,
colour = cond), size = 2.5) +
geom_point(alpha = 1) +
geom_point(data = g1, aes(colour = "Point 15", shape = "Point 15"), size = 4) +
scale_shape_manual(values = c(16, 17, 17) ) +
scale_color_manual(values = c("pink", "turquoise", "blue") ) +
guides(color = guide_legend( override.aes = list(size = c(1.5, 1.5, 4) ) ) )
You probably have to change the condition of that point in the data as in your example or add it to the date, if it is not already part of it.
dat <- data.frame(cond = rep(c("A", "B"), each=10),
xvar = 1:20 + rnorm(20,sd=3),
yvar = 1:20 + rnorm(20,sd=3))
dat$size = 2.5
dat[15,]$cond = "C"
dat$cond = as.character(dat$cond)
dat[15,]$size = 4
ggplot(dat, aes(x = xvar, y = yvar, shape = cond,
colour = cond, size=size)) +
geom_point(alpha = 1) +
scale_colour_manual(values=c("red", "turquoise", "blue")) +
scale_size_continuous(guide = FALSE)

Showing median value in grouped boxplot in R

I have created boxplots using ggplot2 with this code.
plotgraph <- function(x, y, colour, min, max)
{
plot1 <- ggplot(dims, aes(x = x, y = y, fill = Region)) +
geom_boxplot()
#plot1 <- plot1 + scale_x_discrete(name = "Blog Type")
plot1 <- plot1 + labs(color='Region') + geom_hline(yintercept = 0, alpha = 0.4)
plot1 <- plot1 + scale_y_continuous(breaks=c(seq(min,max,5)), limits = c(min, max))
plot1 <- plot1 + labs(x="Blog Type", y="Dimension Score") + scale_fill_grey(start = 0.3, end = 0.7) + theme_grey()
plot1 <- plot1 + theme(legend.justification = c(1, 1), legend.position = c(1, 1))
return(plot1)
}
plot1 <- plotgraph (Blog, Dim1, Region, -30, 25)
A part of data I use is reproduced here.
Blog,Region,Dim1,Dim2,Dim3,Dim4
BlogsInd.,PK,-4.75,13.47,8.47,-1.29
BlogsInd.,PK,-5.69,6.08,1.51,-1.65
BlogsInd.,PK,-0.27,6.09,0.03,1.65
BlogsInd.,PK,-2.76,7.35,5.62,3.13
BlogsInd.,PK,-8.24,12.75,3.71,3.78
BlogsInd.,PK,-12.51,9.95,2.01,0.21
BlogsInd.,PK,-1.28,7.46,7.56,2.16
BlogsInd.,PK,0.95,13.63,3.01,3.35
BlogsNews,PK,-5.96,12.3,6.5,1.49
BlogsNews,PK,-8.81,7.47,4.76,1.98
BlogsNews,PK,-8.46,8.24,-1.07,5.09
BlogsNews,PK,-6.15,0.9,-3.09,4.94
BlogsNews,PK,-13.98,10.6,4.75,1.26
BlogsNews,PK,-16.43,14.49,4.08,9.91
BlogsNews,PK,-4.09,9.88,-2.79,5.58
BlogsNews,PK,-11.06,16.21,4.27,8.66
BlogsNews,PK,-9.04,6.63,-0.18,5.95
BlogsNews,PK,-8.56,7.7,0.71,4.69
BlogsNews,PK,-8.13,7.26,-1.13,0.26
BlogsNews,PK,-14.46,-1.34,-1.17,14.57
BlogsNews,PK,-4.21,2.18,3.79,1.26
BlogsNews,PK,-4.96,-2.99,3.39,2.47
BlogsNews,PK,-5.48,0.65,5.31,6.08
BlogsNews,PK,-4.53,-2.95,-7.79,-0.81
BlogsNews,PK,6.31,-9.89,-5.78,-5.13
BlogsTech,PK,-11.16,8.72,-5.53,8.86
BlogsTech,PK,-1.27,5.56,-3.92,-2.72
BlogsTech,PK,-11.49,0.26,-1.48,7.09
BlogsTech,PK,-0.9,-1.2,-2.03,-7.02
BlogsTech,PK,-12.27,-0.07,5.04,8.8
BlogsTech,PK,6.85,1.27,-11.95,-10.79
BlogsTech,PK,-5.21,-0.89,-6,-2.4
BlogsTech,PK,-1.06,-4.8,-8.62,-2.42
BlogsTech,PK,-2.6,-4.58,-2.07,-3.25
BlogsTech,PK,-0.95,2,-2.2,-3.46
BlogsTech,PK,-0.82,7.94,-4.95,-5.63
BlogsTech,PK,-7.65,-5.59,-3.28,-0.54
BlogsTech,PK,0.64,-1.65,-2.36,-2.68
BlogsTech,PK,-2.25,-3,-3.92,-4.87
BlogsTech,PK,-1.58,-1.42,-0.38,-5.15
Columns,PK,-5.73,3.26,0.81,-0.55
Columns,PK,0.37,-0.37,-0.28,-1.56
Columns,PK,-5.46,-4.28,2.61,1.29
Columns,PK,-3.48,2.38,12.87,3.73
Columns,PK,0.88,-2.24,-1.74,3.65
Columns,PK,-2.11,4.51,8.95,2.47
Columns,PK,-10.13,10.73,9.47,-0.47
Columns,PK,-2.08,1.04,0.11,0.6
Columns,PK,-4.33,5.65,2,-0.77
Columns,PK,1.09,-0.24,-0.92,-0.17
Columns,PK,-4.23,-4.01,-2.32,6.26
Columns,PK,-1.46,-1.53,9.83,5.73
Columns,PK,9.37,-1.32,1.27,-4.12
Columns,PK,5.84,-2.42,-5.21,1.07
Columns,PK,8.21,-9.36,-5.87,-3.21
Columns,PK,7.34,-7.3,-2.94,-5.86
Columns,PK,1.83,-2.77,1.47,-4.02
BlogsInd.,PK,14.39,-0.55,-5.42,-4.7
BlogsInd.,US,22.02,-1.39,2.5,-3.12
BlogsInd.,US,4.83,-3.58,5.34,9.22
BlogsInd.,US,-3.24,2.83,-5.3,-2.07
BlogsInd.,US,-5.69,15.17,-14.27,-1.62
BlogsInd.,US,-22.92,4.1,5.79,-3.88
BlogsNews,US,0.41,-2.03,-6.5,2.81
BlogsNews,US,-4.42,8.49,-8.04,2.04
BlogsNews,US,-10.72,-4.3,3.75,11.74
BlogsNews,US,-11.29,2.01,0.67,8.9
BlogsNews,US,-2.89,0.08,-1.59,7.06
BlogsNews,US,-7.59,8.51,3.02,12.33
BlogsNews,US,-7.45,23.51,2.79,0.48
BlogsNews,US,-12.49,15.79,-9.86,18.29
BlogsTech,US,-11.59,6.38,11.79,-7.28
BlogsTech,US,-4.6,4.12,7.46,3.36
BlogsTech,US,-22.83,2.54,10.7,5.09
BlogsTech,US,-4.83,3.37,-8.12,-0.9
BlogsTech,US,-14.76,29.21,6.23,9.33
Columns,US,-15.93,12.85,19.47,-0.88
Columns,US,-2.78,-1.52,8.16,0.24
Columns,US,-16.39,13.08,11.07,7.56
Even though I have tried to add detailed scale on y-axis, it is hard for me to pinpoint exact median score for each boxplot. So I need to print median value within each boxplot. There was another answer available (for faceted boxplot) which does not work for me as the printed values are not within the boxes but jammed together in the middle. It will be great to be able to print them within (middle and above the median line of) boxplots.
Thanks for your help.
Edit: I make a grouped graph as below.
Add
library(dplyr)
dims=dims%>%
group_by(Blog,Region)%>%
mutate(med=median(Dim1))
plotgraph <- function(x, y, colour, min, max)
{
plot1 <- ggplot(dims, aes(x = x, y = y, fill = Region)) +
geom_boxplot()+
labs(color='Region') +
geom_hline(yintercept = 0, alpha = 0.4)+
scale_y_continuous(breaks=c(seq(min,max,5)), limits = c(min, max))+
labs(x="Blog Type", y="Dimension Score") + scale_fill_grey(start = 0.3, end = 0.7) +
theme_grey()+
theme(legend.justification = c(1, 1), legend.position = c(1, 1))+
geom_text(aes(y = med,x=x, label = round(med,2)),position=position_dodge(width = 0.8),size = 3, vjust = -0.5,colour="blue")
return(plot1)
}
plot1 <- plotgraph (Blog, Dim1, Region, -30, 25)
Which gives (the text colour can be tweaked to something less tacky):
Note: You should consider using non-standard evaluation in your function rather than having it require the use of attach()
Edit:
One liner, not as clean I wanted it to be since I ran into problems with dplyr not properly aggregating the data even though it says the grouping was performed.
This function assume the dataframe is always called dims
library(ggplot2)
library(reshape2)
plotgraph <- function(x, y, colour, min, max)
{
plot1 <- ggplot(dims, aes_string(x = x, y = y, fill = colour)) +
geom_boxplot()+
labs(color=colour) +
geom_hline(yintercept = 0, alpha = 0.4)+
scale_y_continuous(breaks=c(seq(min,max,5)), limits = c(min, max))+
labs(x="Blog Type", y="Dimension Score") +
scale_fill_grey(start = 0.3, end = 0.7) +
theme_grey()+
theme(legend.justification = c(1, 1), legend.position = c(1, 1))+
geom_text(data= melt(with(dims, tapply(eval(parse(text=y)),list(eval(parse(text=x)),eval(parse(text=colour))), median)),varnames=c("Blog","Region"),value.name="med"),
aes_string(y = "med",x=x, label = "med"),position=position_dodge(width = 0.8),size = 3, vjust = -0.5,colour="blue")
return(plot1)
}
plot1 <- plotgraph ("Blog", "Dim1", "Region", -30, 25)
Assuming that Blog is your dataframe, the following should work:
min <- -30
max <- 25
meds <- aggregate(Dim1~Region, Blog, median)
plot1 <- ggplot(Blog, aes(x = Region, y = Dim1, fill = Region)) +
geom_boxplot()
plot1 <- plot1 + labs(color='Region') + geom_hline(yintercept = 0, alpha = 0.4)
plot1 <- plot1 + scale_y_continuous(breaks=c(seq(min,max,5)), limits = c(min, max))
plot1 <- plot1 + labs(x="Blog Type", y="Dimension Score") + scale_fill_grey(start = 0.3, end = 0.7) + theme_grey()
plot1 + theme(legend.justification = c(1, 1), legend.position = c(1, 1)) +
geom_text(data = meds, aes(y = Dim1, label = round(Dim1,2)),size = 5, vjust = -0.5, color='white')

How to merge legends for color and shape when geom_hline has a separate (additional) entry in the color legend?

I have the following code, which produces the following plot:
cols <- brewer.pal(n = 3, name = 'Dark2')
p4 <- ggplot(all.m, aes(x=xval, y=yval, colour = Approach, ymax = 0.95)) + theme_bw() +
geom_errorbar(aes(ymin= yval - se, ymax = yval + se), width=5, position=pd) +
geom_line(position=pd) +
geom_point(aes(shape=Approach, colour = Approach), size = 4) +
geom_hline(aes(yintercept = cp.best$slope, colour = "C2P"), show_guide = FALSE) +
scale_color_manual(name="Approach", breaks=c("C2P", "P2P", "CP2P"), values = cols[c(1,3,2)]) +
scale_y_continuous(breaks = seq(0.4, 0.95, 0.05), "Test AUROC") +
scale_x_continuous(breaks = seq(10, 150, by = 20), "# Number of Patient Samples in Training")
p4 <- p4 + theme(legend.direction = 'horizontal',
legend.position = 'top',
plot.margin = unit(c(5.1, 7, 4.5, 3.5)/2, "lines"),
text = element_text(size=15), axis.title.x=element_text(vjust=-1.5), axis.title.y=element_text(vjust=2))
p4 <- p4 + guides(colour=guide_legend(override.aes=list(shape=c(NA,17,16))))
p4
When I try show_guide = FALSE in geom_point, the shape of the point in the upper legend are all set to default solid circles.
How can I make the lower legend to disappear, without affecting the upper legend?
This is a solution, complete with reproducible data:
library("ggplot2")
library("grid")
library("RColorBrewer")
cp2p <- data.frame(xval = 10 * 2:15, yval = cumsum(c(0.55, rnorm(13, 0.01, 0.005))), Approach = "CP2P", stringsAsFactors = FALSE)
p2p <- data.frame(xval = 10 * 1:15, yval = cumsum(c(0.7, rnorm(14, 0.01, 0.005))), Approach = "P2P", stringsAsFactors = FALSE)
pd <- position_dodge(0.1)
cp.best <- list(slope = 0.65)
all.m <- rbind(p2p, cp2p)
all.m$Approach <- factor(all.m$Approach, levels = c("C2P", "P2P", "CP2P"))
all.m$se <- rnorm(29, 0.1, 0.02)
all.m[nrow(all.m) + 1, ] <- all.m[nrow(all.m) + 1, ] # Creates a new row filled with NAs
all.m$Approach[nrow(all.m)] <- "C2P"
cols <- brewer.pal(n = 3, name = 'Dark2')
p4 <- ggplot(all.m, aes(x=xval, y=yval, colour = Approach, ymax = 0.95)) + theme_bw() +
geom_errorbar(aes(ymin= yval - se, ymax = yval + se), width=5, position=pd) +
geom_line(position=pd) +
geom_point(aes(shape=Approach, colour = Approach), size = 4, na.rm = TRUE) +
geom_hline(aes(yintercept = cp.best$slope, colour = "C2P")) +
scale_color_manual(values = c(C2P = cols[1], P2P = cols[2], CP2P = cols[3])) +
scale_shape_manual(values = c(C2P = NA, P2P = 16, CP2P = 17)) +
scale_y_continuous(breaks = seq(0.4, 0.95, 0.05), "Test AUROC") +
scale_x_continuous(breaks = seq(10, 150, by = 20), "# Number of Patient Samples in Training")
p4 <- p4 + theme(legend.direction = 'horizontal',
legend.position = 'top',
plot.margin = unit(c(5.1, 7, 4.5, 3.5)/2, "lines"),
text = element_text(size=15), axis.title.x=element_text(vjust=-1.5), axis.title.y=element_text(vjust=2))
p4
The trick is to make sure that all of the desired levels of all.m$Approach appear in all.m, even if one of them gets dropped out of the graph. The warning about the omitted point is suppressed by the na.rm = TRUE argument to geom_point.
Short answer:
Just add a dummy geom_point layer (transparent points) where shape is mapped to the same level as in geom_hline.
geom_point(aes(shape = "int"), alpha = 0)
Longer answer:
Whenever possible, ggplot merges / combines legends of different aesthetics. For example, if colour and shape is mapped to the same variable, then the two legends are combined into one.
I illustrate this using simple data set with 'x', 'y' and a grouping variable 'grp' with two levels:
df <- data.frame(x = rep(1:2, 2), y = 1:4, grp = rep(c("a", "b"), each = 2))
First we map both color and shape to 'grp'
ggplot(data = df, aes(x = x, y = y, color = grp, shape = grp)) +
geom_line() +
geom_point(size = 4)
Fine, the legends for the aesthetics, color and shape, are merged into one.
Then we add a geom_hline. We want it to have a separate color from the geom_lines and to appear in the legend. Thus, we map color to a variable, i.e. put color inside aes of geom_hline. In this case we do not map the color to a variable in the data set, but to a constant. We may give the constant a desired name, so we don't need to rename the legend entries afterwards.
ggplot(data = df, aes(x = x, y = y, color = grp, shape = grp)) +
geom_line() +
geom_point(size = 4) +
geom_hline(aes(yintercept = 2.5, color = "int"))
Now two legends appears, one for the color aesthetics of geom_line and geom_hline, and one for the shape of the geom_points. The reason for this is that the "variable" which color is mapped to now contains three levels: the two levels of 'grp' in the original data, plus the level 'int' which was introduced in the geom_hline aes. Thus, the levels in the color scale differs from those in the shape scale, and by default ggplot can't merge the two scales into one legend.
How to combine the two legends?
One possibility is to introduce the same, additional level for shape as for color by using a dummy geom_point layer with transparent points (alpha = 0) so that the two aesthetics contains the same levels:
ggplot(data = df, aes(x = x, y = y, color = grp, shape = grp)) +
geom_line() +
geom_point(size = 4) +
geom_hline(aes(yintercept = 2.5, color = "int")) +
geom_point(aes(shape = "int"), alpha = 0) # <~~~~ a blank geom_point
Another possibility is to convert the original grouping variable to a factor, and add the "geom_hline level" to the original levels. Then use drop = FALSE in scale_shape_discrete to include "unused factor levels from the scale":
datadf$grp <- factor(df$grp, levels = c(unique(df$grp), "int"))
ggplot(data = df, aes(x = x, y = y, color = grp, shape = grp)) +
geom_line() +
geom_point(size = 4) +
geom_hline(aes(yintercept = 2.5, color = "int")) +
scale_shape_discrete(drop = FALSE)
Then, as you already know, you may use the guides function to "override" the shape aesthetics in the legend, and remove the shape from the geom_hline entry by setting it to NA:
guides(colour = guide_legend(override.aes = list(shape = c(16, 17, NA))))

guide_legend and ggplot2, format nrow

I am trying to format an over-long legend on a ggplot so that there is a maximum no. of rows. I've read all the documentation that I could find, especially this: http://docs.ggplot2.org/0.9.3.1/guide_legend.html but for some reason, the legend will not format.
I've given a reproducible sample below using the quakes dataset, and converted the column stations to character so that they plot individually (otherwise, they seem to plot as groups).
plotquakes <- function(magreq) {
library(ggplot2)
magdata <- subset(quakes, mag > magreq)
magdata$stations <- as.character(magdata$stations)
g <- ggplot(magdata, aes (x = lat, y = long))
g + geom_point(aes(alpha = stations), fill = "black", pch=21, size = 6) +
labs(x = "Latitude", y = "Longitude") +
geom_vline(xintercept = 0, col = "red") +
geom_hline(yintercept = 0, col = "red") +
guides(col = guide_legend(nrow = 16))
}
plotquakes(5)
And what I get is this:
whereas I would like to have a maximum of 16 data fields per column in the legend.
You are changing the wrong guide.
plotquakes <- function(magreq) {
library(ggplot2)
magdata <- subset(quakes, mag > magreq)
magdata$stations <- as.character(magdata$stations)
g <- ggplot(magdata, aes (x = lat, y = long))
g + geom_point(aes(alpha = stations), fill = "black", pch=21, size = 6) +
labs(x = "Latitude", y = "Longitude") +
geom_vline(xintercept = 0, col = "red") +
geom_hline(yintercept = 0, col = "red") +
guides(alpha = guide_legend(nrow = 16)) #note it's alpha not col
}
plotquakes(5)

Resources