R ggplot2 could not add legend to graph - r

I'm using visual studio with R version 3.5.1 where I tried to plot legend to the graph.
f1 = function(x) {
return(x+1)}
x1 = seq(0, 1, by = 0.01)
data1 = data.frame(x1 = x1, f1 = f1(x1), F1 = cumtrapz(x1, f1(x1)) )
However, when I tried to plot it, it never give me a legend!
For example, I used the same code in this (Missing legend with ggplot2 and geom_line )
ggplot(data = data1, aes(x1)) +
geom_line(aes(y = f1), color = "1") +
geom_line(aes(y = F1), color = "2") +
scale_color_manual(values = c("red", "blue"))
I also looked into (How to add legend to ggplot manually? - R
) and many other websites in stackoverflo, and I have tried every single function in https://www.rstudio.com/wp-content/uploads/2016/11/ggplot2-cheatsheet-2.1.pdf
i.e.
theme(legend.position = "bottom")
scale_fill_discrete(...)
group
guides()
show.legend=TRUE
I even tried to use the original plot() and legend() function. Neither worked.
I thought there might be something wrong with the dataframe, but I split them(x2,f1,F1) apart, it still didn't work.
I thought there might be something wrong with IDE, but the code given by kohske acturally plotted legend!
d<-data.frame(x=1:5, y1=1:5, y2=2:6)
ggplot(d, aes(x)) +
geom_line(aes(y=y1, colour="1")) +
geom_line(aes(y=y2, colour="2")) +
scale_colour_manual(values=c("red", "blue"))
What's wrong with the code?

As far as I know, you only have X and Y variables in your aesthetics. Therefore there is no need for a legend. You have xlab and ylab to describe your two lines. If you want to have legends, you should put the grouping in the aesthetics, which might require recoding your dataset
d<- data.frame(x=c(1:5, 1:5), y=c(1:5, 2:6), colorGroup = c(rep("redGroup", 5),
rep("blueGroup", 5)))
ggplot(d, aes(x, y, color = colorGroup )) + geom_line()
This should give you two lines and a legend

Related

Is there are a way to change the breaks of a ggplot legend without changing other properties of the aesthetic?

I wish to change the breaks of a ggplot legend without affecting the other properties of the aesthetic (e.g., palette, name, etc.). For example, a MWE where the aesthetic is colour:
## Original plot:
df <- data.frame(x = 1:10, y = 1:10, z = 1:10)
gg <- ggplot(df, aes(x, y, colour = z)) +
geom_point() +
scale_colour_distiller(palette = "Spectral", name = "Original title")
gg
## Plot with adjusted breaks:
gg + scale_colour_distiller(breaks = c(2.5, 7.5))
Original plot
Plot with adjusted breaks
In the second plot, the colour palette and the legend name are reset to their default values: I want to change the legend breaks only.
I understand why the above approach does not work; the first colour scale is completely replaced by the second scale. However, I don't know how to tackle this problem. Any advice is greatly appreciated!
I wrote a function which solves my question. It takes a ggplot object, the name of an aesthetic (as a string), and the breaks for the corresponding legend.
change_legend_breaks <- function(gg, aesthetic, breaks) {
## Find the scales associated with the specifed aesthetic
sc <- as.list(gg$scales)$scales
all_aesthetics <- sapply(sc, function(x) x[["aesthetics"]][1])
idx <- which(aesthetic == all_aesthetics)
## Overwrite the breaks of the specifed aesthetic
gg$scales$scales[[idx]][["breaks"]] <- breaks
return(gg)
}
This is my first time dealing with ggplot objects at a low level, so perhaps there is a better, more robust approach: This works for me, though.
Interestingly, it seems to be a mutating function, that is, it alters the plot object itself, rather than a copy of the object. I didn't know this was possible in R.
As a check that the function works as intended, here is a variant on the original MWE, this time with two aesthetics:
df <- data.frame(x = 1:10, y = 1:10, z1 = 1:10, z2 = 1:10)
gg <- ggplot(df, aes(x, y, colour = z1, size = z2)) +
geom_point() +
scale_size(name = "Original size title") +
scale_colour_distiller(palette = "Spectral", name = "Original colour title")
change_legend_breaks(gg, "colour", breaks = c(2.5, 7.5))
change_legend_breaks(gg, "size", breaks = c(1, 9))

Replace legend labels/texts with Greek (i.e. LaTeX) symbols

I am trying to create a plot containing two lines with different shapes and colour.
I have checked a number of similar questions online but I have not been successful. I have been able to do the following so far
library(reshape2)
library(ggplot2)
library(latex2exp)
v1 <-c(0.000120,-0.000085,-0.000018,0.000005)
v2 <- c(0.000164,0.000041,-0.000032,0.000031)
v3 <- c(500,1000,5000,10000)
dfr <- data.frame(rate1=v1,rate2=v2,quantity=v3)
dfr <- melt(dfr,id='quantity',value.name="res")
ggplot(dfr, aes(x=quantity, y=res,group=variable,shape=variable)) +
geom_line(size=1, aes(linetype=variable,colour=variable)) +
geom_point( size=4,aes(colour=variable))+ coord_cartesian(ylim = c(-0.0001,0.0002)) +
scale_x_continuous(breaks=c(500,1000,5000,10000))+
scale_linetype_manual(values=c("solid", "longdash"))+
geom_hline(yintercept = 0,linetype="dotted",size=1)
However, I want to do the following:
Replace the legend texts/labels: rate1 and rate2 with two Greek lambda symbols.
Finally, hide the legend title variable.
When I try to include this: scale_colour_manual( values=c('#F8766D','#00BFC4'),labels = unname(TeX(c(" $\\lambda_1$", "$\\lambda_2$")))), so as to change the legend text, I get an extra legend below:
Please how can I fix this? Thanks!
The issue is that by changing the labels in scale_linetype but not for the other scales (color and shape) ggplot2 will no longer merge them into one legend. Hence you have the change the labels for the other scales as well. However, using Tex() I did not manage to make this work. But following this post using bquote worked fine. Finally, to get rid of the legend title simply use labs() to set the title for all three scales to NULL
EDIT Thanks to #mischva for checking and pointing out that using labels <- unname(TeX(c(" $\\lambda_1$", "$\\lambda_2$"))) will also work fine. Interestingly it does not work if one puts it directly into the three scales functions. That's what I tried.
library(reshape2)
library(ggplot2)
library(latex2exp)
v1 <-c(0.000120,-0.000085,-0.000018,0.000005)
v2 <- c(0.000164,0.000041,-0.000032,0.000031)
v3 <- c(500,1000,5000,10000)
dfr <- data.frame(rate1=v1,rate2=v2,quantity=v3)
dfr <- melt(dfr,id='quantity',value.name="res")
labels <- c(bquote(lambda[1]), bquote(lambda[2]))
ggplot(dfr, aes(x=quantity, y=res,group=variable,shape=variable)) +
geom_line(size=1, aes(linetype=variable,colour=variable)) +
geom_point( size=4,aes(colour=variable))+ coord_cartesian(ylim = c(-0.0001,0.0002)) +
scale_x_continuous(breaks=c(500,1000,5000,10000))+
scale_linetype_manual(values=c("solid", "longdash"), labels = labels)+
scale_shape_discrete(labels = labels)+
scale_colour_discrete(labels = labels) +
labs(color = NULL, linetype = NULL, shape = NULL) +
geom_hline(yintercept = 0,linetype="dotted",size=1)

Two plots in one plot with ggplot

I need to create "two plots" in "one plot" with ggplot. I managed to do it with base R as follows:
x=rnorm(10)
y=rnorm(10)*20+100
plot(1:10,rev(sort(x)),cex=2,col='red',ylim=c(0,2.2))
segments(x0=1:10, x1=1:10, y0=1.8,y1=1.8+y/max(y)*.2,lwd=3,col='dodgerblue')
However, I am struggling with ggplot, how can it be done?
Here's one possible translation of that code.
ggplot(data.frame(idx=seq_along(x), x,y)) +
geom_point(aes(idx, rev(sort(x))), col="red") +
geom_segment(aes(x=idx, xend=idx, y=1.8, yend=1.8+y/max(y)*.2), color="dodgerblue")
In general with ggplot2, you can add multiple views of data to a plot by adding additional layers (geoms)
My solution is similar to #MrFlick.
I would always recommend having a plot data frame and referring to the variables from there as you can more easily relate variables to plot aesthetics.
library(tidyverse)
plot_df <- data.frame(x, y) %>%
arrange(-x) %>%
mutate(id = 1:10)
ggplot(plot_df) +
geom_point(aes(id, x), color = "red", pch = 1, size = 5) +
geom_segment(aes(x = id, xend = id, y = 1.8, yend = 1.8+y/max(y)*.2),
lwd = 2, color = 'dodgerblue') +
scale_y_continuous(limits = c(0,2.2)) +
theme_light()
Ultimately, the goal of ggplot is to add aesthetics (in this case, the points and the segments) to form the final plot.
If you'd like to learn more, check out the ggplot cheat sheet and read more on the ideas behind ggplot: https://ggplot2.tidyverse.org/

Add multiple legends to ggplot geom_tile

I'm using ggplot to create a heat-map style plot, and would like to add a second legend with the data scaled a different way. I'm wondering if there is a simple way to do this.
I do not believe that this is a duplicate of other "multiple legends" questions e.g. Multiple legends for a ggplot in R as crucially I want to add extra legends for the same aesthetic - i.e. one aesthetic mapping, two legends.
Example code
# Create a dataframe with some dummy data
x <- c()
y <- c()
for(i in 1:100){
for(j in 1:100){
x <- c(x, i)
y <- c(y, j)
}
}
example_data <- data.frame(x, y)
example_data$z <- example_data$x*example_data$y
example_data$z_rescale <- example_data$z*0.5
Now we've got some data that I'd like to plot as a heatmap with "z" as a colour gradient.
ggplot(example_data, aes(x = x, y = y, fill = z)) +
geom_tile() +
scale_fill_gradient(low = "blue", high = "red") +
scale_x_continuous(expand = c(0, 0)) +
scale_y_continuous(expand = c(0, 0))
Doing the same with the rescaled z gives an identical plot, but with the rescaled legend:
ggplot(example_data, aes(x = x, y = y, fill = z_rescale)) +
geom_tile() +
scale_fill_gradient(low = "blue", high = "red") +
scale_x_continuous(expand = c(0, 0)) +
scale_y_continuous(expand = c(0, 0))
What I'd like to do however is have a single plot showing the two different legends, which would look something like this mock-up:
Now, I imagine this would be possible by creating two plots, finding the grob that represents the legend in one of the plots and cunningly adding it to the second plot... however, is there a much simpler way that I'm overlooking?
Many thanks!
Please add the code
aes(color = z_rescale) +
scale_color_gradient(low = "blue", high = "red") +
after geom_tile() line and you will get the desired

changing ggplot legend unit scale

This question is motivated by a previous post illustrating various ways to change how axes scales are plotted in a ggplot figure, from the default exponential notation to the full integer value (when ones axes values are very large). While I am able to convert the axes scales from exponential notation to full values, I am unclear how one would achieve the same goal for the values appearing in the legend.
While I understand that one can manually change the length of the legend scale with "scale_color..." or "scale_fill..." followed by the "limits" argument, this does not appear to be a solution to getting my legend values to show "6000000000" rather than "6e+09" (or "0" rather than "0e+00" for that matter).
The following example should suffice. My hope is someone can point out how to implement the 'scales' package to apply for legend scales rather than axes scales.
Thanks very much.
library(ggplot2)
library(scales)
Data <- data.frame(
pi = c(2,71,828,1828,45904,523536,2874713,52662497,757247093,6999595749),
e = c(3,14,159,2653,58979,311599,7963468,54418516,1590576171, 99),
face = 1:10)
p <- ggplot(data = Data, aes(x=face, y=e, colour = pi))
myplot <- p + geom_point() +
scale_y_continuous(labels = comma) +
scale_color_gradientn(colours = rainbow(2), limits=c(0,7000000000))
myplot
Use the Comma formatter in scale_color_gradientn by setting labels = comma e.g.:
p <- ggplot(data = Data, aes(x=face, y=e, colour = pi))
myplot <- p + geom_point() +
scale_y_continuous(labels = comma) +
scale_color_gradientn(colours = rainbow(2), limits=c(0,7000000000), labels = comma)
myplot

Resources