Multiple Lines for Text Per Legend Label in Ggplot2

Multiple Lines for Text per Legend Label in ggplot2

You can use str_wrap for automated wrapping of long strings or you can hard code breaks by adding \n (the line break character) to a string. To add space between the legend keys, you can use the legend.key.height theme element. Here's an example with the built-in iris data frame:

library(stringr)
library(tidyverse)

# Create long labels to be wrapped
iris$Species = paste(iris$Species,
"random text to make the labels much much longer than the original labels")

ggplot(iris, aes(Sepal.Length, Sepal.Width, colour=str_wrap(Species,20))) +
geom_point() +
labs(colour="Long title shortened\nwith wrapping") +
theme(legend.key.height=unit(2, "cm"))

Sample Image

Multiple Fixed Lines for Text per Legend Label in ggplot2

You can use ggtext and use element_markdown() in your theme which gives you a lot of flexibility:

library(ggplot2)
library(dplyr)
set.seed(10)
dat_sof<-tibble(x=seq(1:10))%>%
mutate(y=x+rnorm(10))

leg_col<-c("S1"="blue", "S2"='black')
leg_lty<-c("S1"=1, "S2"=2)
leg_lab <- c("S1:<br>y = m1x + b1<br>R<sup>2</sup> = r1, n = n1",
"S1:<br>y = m2x + b2<br>R<sup>2</sup> = r2, n = n2")
ggplot(data=dat_sof, aes(x=x, y=y))+
geom_point()+
geom_smooth(method='lm', aes(color="S1", lty="S1"), se=F)+
geom_abline(aes(color="S2", lty="S2", slope=1, intercept=0.1))+
theme_bw(base_size=14)+
scale_color_manual(values=leg_col, name="Regressions", labels=leg_lab)+
scale_linetype_manual(values=leg_lty, name="Regressions", labels=leg_lab)+
theme(legend.text.align = 0,
legend.text = ggtext::element_markdown(),
legend.key.height=unit(2, "cm"))

Sample Image

Multi-line legend text including exponent with ggplot

You can use the unicode representation of superscript two (U+00B2) and avoid the
problem-causing combination of expression() and a multi-line legend title:

ggplot(plotdt, aes(data_groups)) +
geom_bar(aes(weight=moisture_level, fill=leakage_rates), position='dodge') +
labs(y='Moisture Level') +
labs(fill=paste('Leakage Rate\nat 75 Pa\n(L/s-m\u00b2)', sep='')) +
theme(panel.grid.major.x = element_blank(),
axis.title.x = element_blank())

Plot using Superscript

How Insert an expression in legend in ggplot2?:: correct color + multiple lines and point

Ironically, setting this up with conventional ploting is rather simple:

Given all the data above:


linetypes4 <- c( Xb_exp=NA, Xb_dw="solid", Xb_f="dotted", Xb_s="longdash" )

plot(
NA, type="n", xlim=c(0,30), ylim=c(0,0.8),
xlab = "Crank position (ºCA)", ylab = bquote('Burn fraction ('~X[b]~')'),
panel.first = grid()
)
with( dat, {
points( x=CA, y=Xb_exp, pch=19, col=color4["Xb_exp"], size=3 )
for( n in c("Xb_dw", "Xb_f", "Xb_s")) {
lines( x=CA, y=get(n), lty=linetypes[n], col=color4[n], lwd=2 )
}
})
legend(
x = "right",
legend = labels,
col = color4,
lty = linetypes4,
pch = c(19,NA,NA,NA),
box.lwd = 0,
inset = .02
)

with proper labels

ggplot2: Make multiple line+ribbon's with legend

Maybe this is what you are looking for ...

  1. General lesson: If you want a legend you have to map somethin on an aesthetic, i.e. put color and/or fill inside aes()

  2. Neither your wide nor your long dataset are suitable for easy plotting. Instead, starting from your long df, I first get rid of the numbers in your line column and make the dataset wider so we have just y, ymin, ymax (after doing so we end up with tidy data, as 1 and 2 are categories of one variabale, while y, ymin, ymax are different variables). This allows us to set up your plot with only two geom layers. Additonally we don't have to use complicated and error prone codelike longDF$x[longDF$line=="y2"] to get the values we like to plot.

  3. For the text labels I use group_by(longDF1, fill) %>% top_n(1, x) as data which simply picks the rows for each line with the top x value.

  4. Finally, to get the colors right set them via scale_xxx_manual

library(dplyr)
library("ggplot2")
library("tidyr") # for pivot_longer()

# Set up data:
set.seed(47405)
x = 1:10
y1 = 1 + 0.1*x + rnorm(length(x),0,0.2) # line 1
y2 = 2 + 0.2*x + rnorm(length(x),0,0.2) # line 2
y1lo = y1 - 0.2 # ribbon 1 low
y1hi = y1 + 0.2 # ribbon 1 high
y2lo = y2 - 0.3 # ribbon 2 low
y2hi = y2 + 0.3 # ribbon 2 high

# Wide format data frame:
wideDF = data.frame( x=x ,
y1lo=y1lo , y1=y1 , y1hi=y1hi ,
y2lo=y2lo , y2=y2 , y2hi=y2hi )

# Long format data frame:
longDF = pivot_longer( wideDF , cols=!x , names_to="line" , values_to="y" )
longDF$fill = NA
longDF$fill[grep( "1" , longDF$line )] = "y1"
longDF$fill[grep( "2" , longDF$line )] = "y2"

longDF1 <- longDF %>%
mutate(line = gsub("\\d", "", line)) %>%
pivot_wider(id_cols = c(x, fill), names_from = line, values_from = y)

ggplot(longDF1) +
geom_ribbon(aes(x=x, ymin=ylo, ymax=yhi, fill = fill), alpha=0.5) +
geom_line(aes(x=x, y=y, color = fill)) +
labs( title="Using LONG data frame" , y="Y label" , x="X label" ) +
geom_text(data = group_by(longDF1, fill) %>% top_n(1, x),
aes(x = x, y = y, label = toupper(fill), color = fill),
hjust = 1 , vjust = -0.5, show.legend = FALSE) +
scale_color_manual(values = c(y1 = "red", y2 = "blue")) +
scale_fill_manual(values = c(y1 = "pink", y2 = "lightblue"))

how to put legend as a label in the middle of line in ggplot2

You can add annotate to your lines. You can use the following code:

library(tidyverse)
df<- data.frame(direct= 10:85, indirect= 55:130, age=15:90)

ggplot(data=df)+
geom_line(mapping=aes(y=direct,x= age,color="direct"),linetype="dashed" ) +
geom_line(mapping=aes(y=indirect,x= age,color="indirect"),linetype="solid") +
scale_color_manual(values = c(
'direct' = 'black',
'indirect' = 'black')) +
labs(color = NULL)+
scale_x_continuous(breaks = seq(15, 90, by = 5))+
labs(y= "Time Spent (in minutes)")+
guides(color = guide_legend(override.aes = list(linetype = c("solid","dashed"))))+
theme_classic()+
theme(plot.title = element_text(hjust = 0.5, size=9, face="bold"), legend.position = "none") +
annotate('text', x=50, y=55, label = "direct")+
annotate('text', x=50, y=100, label = "indirect")

Output:

Sample Image

How to align legend symbol with wrapped legend text on ggplot2

Here's one solution that is sort of a hack by changing the background color to white and using vjust. I couldn't find an easy way to top-align the point within the box...

library(stringr)
library(tidyverse)
# Create long labels to be wrapped
iris$Species = paste(iris$Species,
"random text to make the labels much much longer than the original labels")

ggplot(iris, aes(Sepal.Length, Sepal.Width, colour=str_wrap(Species,20))) +
geom_point() +
labs(colour="Long title shortened\nwith wrapping") +
theme(legend.key.height=unit(2, "cm"), legend.key = element_rect(fill = "white")) +
guides(colour = guide_legend(label.vjust = -1, label.position = "right"))

Created on 2019-01-28 by the reprex package (v0.2.1)

Editing legend (text) labels in ggplot

The tutorial @Henrik mentioned is an excellent resource for learning how to create plots with the ggplot2 package.

An example with your data:

# transforming the data from wide to long
library(reshape2)
dfm <- melt(df, id = "TY")

# creating a scatterplot
ggplot(data = dfm, aes(x = TY, y = value, color = variable)) +
geom_point(size=5) +
labs(title = "Temperatures\n", x = "TY [°C]", y = "Txxx", color = "Legend Title\n") +
scale_color_manual(labels = c("T999", "T888"), values = c("blue", "red")) +
theme_bw() +
theme(axis.text.x = element_text(size = 14), axis.title.x = element_text(size = 16),
axis.text.y = element_text(size = 14), axis.title.y = element_text(size = 16),
plot.title = element_text(size = 20, face = "bold", color = "darkgreen"))

this results in:

Sample Image

As mentioned by @user2739472 in the comments: If you only want to change the legend text labels and not the colours from ggplot's default palette, you can use scale_color_hue(labels = c("T999", "T888")) instead of scale_color_manual().



Related Topics



Leave a reply



Submit