ggplot2 produces two legends instead of one - r

I am trying to do a simple logged ggplot, showing the change in tree and shrub density over time (site age). the tree species are split into native / exotic.
I have also downloaded the viridis package, to enable a type of coloration to the legend+line+points+confidence interval fill.
The problem is, when I do plot using the viridis code, I get two separate legends, which I don't want. I can't figure out how to keep the viridis legend, and remove the other legend.
I would love to provide a picture of my output - but can't figure out how to add it to this question template...
this is the code I have used:
attach(data.df4)
base <- ggplot(data.df4, aes(age, total_trees))
base +
theme_classic(base_size = 10, base_family = "times") +
scale_y_log10() +
geom_point(aes(color = status)) +
geom_smooth(aes(color = status, fill = status), method = "lm", se = TRUE) +
scale_colour_viridis(discrete = TRUE, option = "D")+
scale_fill_viridis(discrete = TRUE, option = "D") +
labs(title = "changes in planted canopy and subcanopy tree and shrub density over time",
x = "planting age",
y = "density (plot-level)")

Without seeing your data or a screenshot, it's hard to know what needs to change. You can remove legends you don't want in 2 different ways
turn off the fill legend ggplot() + guides(fill = FALSE)
specify not to create a legend within the layer geom_smooth(..., show.legend = FALSE)
This article can show you how to post some sample data:
https://reprex.tidyverse.org/articles/articles/datapasta-reprex.html

Related

Is there a way to add multiple horizontal lines to a plot with different symbology and a legent?

I need to add horizontal lines (similar to geom_hline) to a plot but retain the ability to add symbology (e.g. different dashed or dotted line) to each and have them appear in a legend. The y-intercept of each comes from the "Concentration" variable and the label needs to come from "Type". I've created an example dataset at the bottom of the question but the one I'm working with is a lot larger, with about 30 different Pesticides and up to 4 Types within each. I am hoping to split and sapply to automate plotting across the entire dataset.
Here is the plot code that I've tried so far and you can see the geom_hline works (as in, the lines appear on the plot), but it doesnt give the ability to change symbology of each or add a legend. Please ignore the box plots and jitter - they arent relevant to this question.
Is there a way i can add these lines to the plot, each with different symbology and a legend to capture that?
Thanks in advance
Plot2 <- ggplot(PestDat, aes(x=factor(Phyla), y=Conc_ug)) +
geom_boxplot(color="dark gray", fill = 'dark gray', alpha = 0.1) +
geom_jitter(aes(shape = Pathway), height=.3, width=.3, size = 1.5) +
scale_y_continuous(trans='log10') +
geom_hline(data = PestDat,aes(yintercept = Concentration),linetype="dashed") +
labs(x = "Phyla", y = "Log10 Concentration (µg/L)") +
labs(title = (unique(ToxDat_Diuron$Pesticide)),
subtitle = "Do we want a subtitle for the plot?",
caption = "Source: Citation, Reliability ?? ")
Plot2
Sample data
PestDat <- data.frame(
Pest = c("Diuron","Diuron","Diuron","Diuron","Atrazine"),
Type = c("PC99","PC95","PC90","PC80","ETV"),
Concentration = c(0.1,0.2,0.3,0.4,0.7),
stringsAsFactors = FALSE)
We can put the linetype aesthetic inside the aes() term to make it use the variable from the data to categorize the type of line. Note that linetype wants a discrete variable, so in this case I used A-B-C.
ggplot(PestDat, aes(x=factor(Pest), y=Concentration)) +
geom_boxplot(color="dark gray", fill = 'dark gray', alpha = 0.1) +
geom_jitter(aes(shape = Type), height=.3, width=.3, size = 1.5) +
scale_y_continuous(trans='log10') +
labs(x = "Phyla", y = "Log10 Concentration (µg/L)",
subtitle = "Do we want a subtitle for the plot?") +
geom_hline(data = data.frame(y_int = c(0.6,0.9, 1.1),
type = c("C","B","A")),
aes(yintercept = y_int, linetype = type))

How can I adjust the linetype in an already existing ggplot model in R?

To examine an interaction effect in my research I've created post hoc slopes using the function “emtrends” of the package emmeans (version 1.4.5.; Lenth, 2020) and visualized it in a plot using 'emmip'. I've used the code below:
emtrends(model_c, pairwise ~ Condition, var = "prsa_clean$meat_amount_c")
emmip(model_c, Condition ~ meat_amount_c, cov.reduce = range, ylab = "Favourability", xlab = "Meat consumption")
The resulting plot shows the 3 slope lines of my 3 conditions in blue/green/red lines, but doesn't adhere to the APA standards for figures, so I'm trying to adjust it using ggplot2. I manage to successfully edit the background and linesizes to my liking using the code below:
plot <- emmip(model_c, Condition ~ meat_amount_c, cov.reduce = range, ylab = "Favourability", xlab = "Meat consumption")
plot <-plot +theme_bw() + geom_line(size = 1.25)
However, I would like the lines to be different types. I've found the appropriate code to adjust this with ggplot is to use the function geom_line(linetype = ""). I've tried to add the code in the same way as the theme and linesize, but it doesn't work. Example tries of code below:
plot <- plot +theme_bw() + geom_line(size = 1.25) + geom_line(linetype = "dashed")
plot <- plot +theme_bw() + geom_line(size = 1.25) + geom_line(aes(linetype = Condition))
plot <- plot +theme_bw() + geom_line(size = 1.25) + scale_linetype_manual(values=c("twodash", "dotted", "solid"))
I'm not a regular R user so I'm probably missing something pretty obvious. I hope someone can help me out.
In sum, I expected the geom_line(linetype="") argument to change the existing lines in the plot to become the designated types, but they remained unchanged. The theme_() and geom_line(size=) worked similarly so I expected similar results.
Following my comment I tried some things with the emmip helpfile examples.
You can change line size within emmip with linearg = list(size = 1.25)
You can add scale_linetype_manual to the output
Example code:
library(emmeans)
noise.lm = lm(noise ~ size * type * side, data = auto.noise)
emmip(noise.lm, type ~ side * size, CIs = TRUE,
linearg = list(size = 1.25)) +
ggplot2::scale_linetype_manual(values=c("twodash", "dotted"))

How do I properly set up the legend to my linear mixed model using ggplot?

I have built a linear mixed effects model and I'm trying to plot it using ggplot but it keeps giving me problems with my legend. It's ordered wrong, or I get two legends, or the symbols get mixed up, or a combination of all three. This is driving me insane and I can't believe that it's this complicated. Here's my code:
g1 <- ggplot(SpotGrowth_longform,
aes(x = spotage, y = spotprop, color = treatment)) +
geom_point(aes(shape = treatment)) +
labs(x = "Hours Since White Spot First Detected",
y = "Proportion of Egg Surface Area") +
guides(color = guide_legend("% Oxygen")) +
theme_classic() +
stat_smooth(method = "lm", se = TRUE) +
theme(legend.position = c(.1, .8)) +
scale_color_manual("% Oxygen", values = c("red", "orange", "green", "blue","black"))
g1
My independent variables/fixed effects are spotage and treatment. The dependent variable is spotprop. Also, treatment is a grouping factor (% oxygen) that I used for the mixed effect analysis. spotage and spotprop are numeric fields, treatment is a factor.
The code above give me this chart (can't post image?):
https://drive.google.com/file/d/1OWpESx0ES_5ha2rL75pHDtWoj1HcKgd0/view?usp=sharing
I feel like I'm almost there because all I want is to make the lower legend, the one titled "% Oxygen" that also has the shading for the CIs, show the shapes that are called out in the upper legend - and I'd like to have them ordered descending so they match the chart, and, if possible, show significant differences between groups with letters or stars or whatever. Obviously I am missing something important but nothing I've read online solves this exact problem.
I guess I should mention that I would prefer not to use colors at all, that's why I want to have unique point shapes for each treatment.
I will share the data with the forum if someone will tell me how to do it. It is formatted long form and has 487 rows of data.
I think you need to add a line guides(shape = guide_legend("% Oxygen")) + where the shape legend name matches the color legend name for them to be combined.
Here an example using mtcars data to be reproducible:
ggplot(mtcars,
aes(x = wt, y = mpg, color = as.character(cyl))) +
geom_point(aes(shape = as.character(cyl)), size = 5) +
labs(x = "Hours Since White Spot First Detected",
y = "Proportion of Egg Surface Area") +
guides(color = guide_legend("% Oxygen", reverse = TRUE),
shape = guide_legend("% Oxygen", reverse = TRUE)) +
theme_classic() +
stat_smooth(method = "lm", se = TRUE) +
theme(legend.position = c(.5, .8)) +
scale_color_manual("% Oxygen", values = c("gray80", "gray50", "gray20"))

How to create a legend title in a ggplot2 line graph

I am creating a line graph using the ggplot2 package in R.
I cannot upload the data as it is for a study I am conducting for my final year project. So, I can only share the code with you.
This is the code for the APA formatted graph.
ggplot(accuracy_data,
aes(x = eccentricity, y = accuracy, group= speech_task)) +
geom_line(aes(linetype=speech_task)) +
scale_linetype_manual(values=c("twodash", "dotted", "solid")) +
geom_point(aes(shape = speech_task)) +
facet_grid(. ~ duration, labeller=labeller(duration = labels)) +
labs(x='Eccentricity (degrees of visual angle)', y='Accuracy of responses') +
theme_apa() +
theme(text=element_text(family='Times')) +
scale_x_continuous(breaks =c(5, 10, 15)) +
geom_errorbar(aes(ymin = accuracy - acc_sum$se , ymax = accuracy + acc_sum$se ), width=.1)
This produces a graph with a legend without a title, hence I am asking for help in creating a title for the legend.
I have tried a lot of different options however none work. I don't even get an error message.
These are the codes I have tried so far:
legend_title <- "Speech Task"
scale_fill_manual(legend_title,values=c("Conversation", "N-Back", "Silence"))
guides(fill=guide_legend(title="Speech Task"))
scale_fill_discrete(name = "Speech Task",
labels = c("Conversation", "N-Back", "Silence"))
labs(fill="Speech Task")
The following and final code I tried was the only one to produce a change in the graph. However because I have manually changed the point shape as well as line type it caused two legends to be made and only titled the line type legend.
labs(linetype= "Speech Task")
Please can I have some help :)
Seeing no data or final results I'm going on a hunch here.
I suspect you need to name shape and fill legends the same. So something along the lines of
scale_linetype_manual(name = legend_title, values = c("twodash", "dotted", "solid")) +
scale_fill_manual(name = legend_title, values = c("Conversation", "N-Back", "Silence")) +

'Merging' two plots using ggplot2 and R

Given the following dataset:
data = cbind(1:10,c('open','reopen','closed'),letters[1:3],1:10)
data = rbind(data,cbind(1:10,c('open','closed','reopen'),letters[1:3],5:10))
data = rbind(data,cbind(1:10,c('closed','open','reopen'),letters[1:3],3:10))
data = data.frame(data);
colnames(data) <- c("id","status","author","when")
I'd like to get a plot similar to the following:
ggplot(data, aes(when,id)) +
geom_line(aes(group = id,colour = status)) +
geom_point(aes(group = id,colour = author))
But, as such I get a single legend by 'author' with the status and author values. How can I get the same result but with a legend for author and other for status? My rationale is that I want to layer two plots of the same dataset on top of each other.
I don't think you can have different color scales / legends for one ggplot. You could hack something together (see this question for legend hacking), but in this case where one of your geom's is point, you could just use fill and one of the point options that are filled in.
ggplot(data, aes(when,id)) +
geom_line(aes(group = id,colour = status)) +
geom_point(aes(group = id, fill = author),
shape = 21, color = NA, size = 4)
Here the colors used are the same for each, but you can edit the color or fill scales individually, e.g., adding
scale_fill_brewer(type = "qual") +
scale_color_brewer(type = "qual", palette = 2)
I do agree with AndyClifton that using color in two ways will be hard to distinguish. You could also experiment with line types, point shapes, or even plotting with geom_text using a word, a letter, or a number as a label instead of points. You say you have more than 6 values for author, but it will be very difficult to distinguish more than 6 colors for author, especially when color is also being used for status.
Let's take your data. First you should be aware that you have a problem that your when and id column is a string, so you are plotting 1, 10, 2, 3, ... not 1,...9,10. We can fix that:
data$when.num <-as.numeric(as.character(data$when))
data$id.num <-as.numeric(as.character(data$id))
Then we'll plot it but use different shapes to get two different legends:
require(ggplot2)
p <- ggplot(data, aes(x = when.num, y = id)) +
geom_line(aes(group = id,colour = status)) +
geom_point(aes(group = id,shape = author))
print(p)
And you get this:
I think this is much clearer than using coloured points for the author, but this is a question of taste.

Resources