This question already has an answer here:
How to insert a legend in a GGPLOT with multiple time series
(1 answer)
Closed 2 years ago.
So this is the graph and the code I have so far:
library(fivethirtyeight)
library(tidyverse)
bad_drivers$num_drivers
bad_drivers$perc_speeding
mytable <- bad_drivers %>%
mutate(SpeedPerBilion = (num_drivers * perc_speeding)/100)
ggplot(data = mytable, aes(x = state, y = SpeedPerBilion, fill='red')) +
xlab("") +
ylab("") +
coord_flip() +
geom_bar(stat = "identity")+
geom_bar(data= mytable, aes(x = state, y=num_drivers), alpha=0.5,stat="identity") +
theme(plot.title =`enter code here` element_text(face = "bold"), legend.position = "none")+
scale_y_continuous(sec.axis = dup_axis())+
labs(title = "Drviers Involved In Fatal Collisions While Speeding",
subtitle = "As a share of the number of fatal collisions per billion miles, 2009")
So my questions are:
How am I adding a legend to this graph?
How to erase this lower y coordinate (so to have just the upper one)?
Thank you in advance! :)
Find code below and what I believe is your desired plot. You will have to tweak labels to match what you need but I put place holder names. The key is using the scale_fill_manual with a named vector of colors and calling those color names in the aes of each layer you need to use that color in. Also a neat trick is using alpha() to apply alpha as a color rather than a separate scale. Finally the y axis transformation you were looking for is position = "right" so it ends up on top after coord_flip().
library(fivethirtyeight) # for data
library(tidyverse)
bad_drivers %>%
mutate(SpeedPerBilion = (num_drivers * perc_speeding)/100) %>%
ggplot(aes(x = state, y = SpeedPerBilion)) +
xlab("") +
ylab("") +
coord_flip() +
geom_bar(stat = "identity", aes(fill = "Speeding")) +
geom_bar(aes(x = state, y = num_drivers, fill = "All"),
stat = "identity") +
theme(plot.title = element_text(face = "bold")) +
scale_y_continuous(position = "right") +
scale_fill_manual(name = "Speeding Involved",
values = c("Speeding" = alpha("red", 1), "All" = alpha("red", 0.5))) +
labs(title = "Drviers Involved In Fatal Collisions While Speeding",
subtitle = "As a share of the number of fatal collisions per billion miles, 2009") +
guides(fill = guide_legend(override.aes = list(color = "red", alpha = c(0.25, 1))))
Created on 2022-10-11 by the reprex package (v2.0.1)
Note: For some reason the transparency in the legend doesn't look the same as in the plot so I manually set the legend to alpha = 0.25 so to my eye it matches the plot. Please confirm the result on your own computer.
Maybe this:
library(fivethirtyeight)
library(tidyverse)
mytable <- bad_drivers %>%
mutate(SpeedPerBilion = (num_drivers * perc_speeding)/100)
ggplot(data = mytable, aes(x = state, y = SpeedPerBilion, fill='red')) +
xlab("") +
ylab("") +
coord_flip() +
geom_bar(stat = "identity")+
geom_bar(data= mytable, aes(x = state, y=num_drivers), alpha=0.5,stat="identity") +
scale_y_continuous(sec.axis = dup_axis())+
theme(plot.title = element_text(face = "bold"),
axis.text.x.bottom = element_blank(),
axis.ticks.x.bottom = element_blank())+
labs(title = "Drviers Involved In Fatal Collisions While Speeding",
subtitle = "As a share of the number of fatal collisions per billion miles, 2009")
Output:
Related
enter image description hereI am having a problem with my ggplot that i cannot insert a legend. I just want to show the total number of facilities per region (manually).
Here is my code:
Note: my csv file has 17,333 IDs, I was thinking maybe that is why but I'm not really sure so.
library(ggplot2)
library(dplyr)
library(ggthemes)
library(tidyverse)
doh = read.csv("doh.csv")
doh %>%
ggplot(aes( y = region, color = region)) +
geom_bar(position = "identity", size = 0.7, alpha = 0.8, fill = "#28d1eb", colour="black") +
labs(title = "Total Number of COVID-19 Facilities per Region",
x = "Count",
y = "Region") +
theme_minimal() +
theme(plot.title = element_text(lineheight=6, face="bold", color="black",size=15))
I have tried inserting a legend in my code but it isn't working and I'm not sure where I went wrong.
code:
library(ggplot2)
library(dplyr)
library(ggthemes)
library(tidyverse)
doh = read.csv("doh.csv")
doh %>%
ggplot(aes( y = region, fill = region, color = region)) +
geom_bar(position = "identity", size = 1.0, alpha = 0.8, fill = "#28d1eb", colour="black") +
labs(title = "Total Number of COVID-19 Facilities per Region") +
theme_minimal() +
theme(plot.title = element_text(lineheight=6, face="bold", color="black",size=15)) +
barplot(data,
col = c("#f2b50c", "#d96fe3")) +
legend("topright",
legend = c("REGION XIII (CARAGA)"))
PS: I only included the "REGION XIII (CARAGA)" because I just want to see if its working but its not.
enter image description here
Thanks in adv!
Here is a way. Count the regions before piping to ggplot.
The example below uses the data set diamonds, substitute region for clarity and the code should work.
suppressPackageStartupMessages({
library(ggplot2)
library(dplyr)
})
data(diamonds)
diamonds %>%
select(clarity) %>%
count(clarity, name = "Count") %>%
ggplot(aes(x = clarity, y = Count, fill = clarity)) +
geom_col(alpha = 0.8, fill = "#28d1eb", colour = "black") +
geom_text(aes(label = Count), hjust = -0.1) +
coord_flip() +
labs(title = "Total Number of COVID-19 Facilities per Region") +
theme_minimal(base_size = 15) +
theme(plot.title = element_text(lineheight = 6, face = "bold", color="black"))
Created on 2022-11-21 with reprex v2.0.2
I wanted the barplot to appear in two forms, so I created repeated data and used it as an input.
So I used the data in the form below.
I put the data in the form above and wrote the following code to use it.
Select <- "Mbp"
if(Select == "Mbp"){
Select <- "Amount of sequence (Mbp)"
} else if (Select == "Gbp"){
Select <- "Amount of sequence (Gbp)"
}
ggplot(G4, aes(x = INDV, y = Bp, fill = Group)) + theme_light() +
geom_bar(stat = 'identity', position = 'dodge', width = 0.6) + coord_flip() +
scale_x_discrete(limits = rev(unname(unlist(RAW_TRIM[1])))) +
scale_fill_discrete(breaks = c("Raw data","Trimmed data"))+
scale_y_continuous(labels = scales::comma, position = "right") +
theme(axis.text = element_text(colour = "black", face = "bold", size = 15)) +
theme(legend.position = "bottom", legend.text = element_text(face = "bold", size = 15),
legend.title = element_blank()) + ggtitle(Select) + xlab("") + ylab("") +
theme(plot.title = element_text(size = 25, face = "bold", hjust = 0.5))
Then I can get a plot like the one below, where I want the red graph to be on top of the green graph.
I also tried changing the order of the data, and several sites such as the Internet and Stack Overflow provided solutions and used them, but not a single solution was able to solve them.
If you know a solution, please let me know how to modify the code or change the data.
thank you.
You seem to be asking more than one question at once here, but the main one is: why do the bars for Raw appear under those for Trimmed? The short answer is: factor levels and the behaviour of coord_flip().
Let's make a toy dataset:
library(tidyverse)
G4 <- data.frame(INDV = c("C_01", "C_01", "C_41", "C_41"),
Group = c("Raw data", "Trimmed data", "Raw data", "Trimmed data"),
Bp = c(200, 100, 500, 400))
A simple dodged bar chart. Note that Raw comes before Trimmed, because R is before T in the alphabet:
G4 %>%
ggplot(aes(INDV, Bp)) +
geom_col(aes(fill = Group),
position = "dodge")
Now we coord_flip:
G4 %>%
ggplot(aes(INDV, Bp)) +
geom_col(aes(fill = Group),
position = "dodge") +
coord_flip()
This has the effect of reversing the variables, so Raw is now below Trimmed.
We can fix that by altering factor levels. As there are only two groups we can just reverse them using fct_rev() from the forcats package:
G4 %>%
ggplot(aes(INDV, Bp)) +
geom_col(aes(fill = fct_rev(Group)),
position = "dodge") +
coord_flip()
The bar for Raw is now on top but unfortunately, the colours are now reversed so that Raw bars are green. We can fix that using scale_fill_manual():
G4 %>%
ggplot(aes(INDV, Bp)) +
geom_col(aes(fill = fct_rev(Group)),
position = "dodge") +
coord_flip() +
scale_fill_manual(values = c("#00BFC4", "#F8766D"))
Now the Raw bars are on top, and they are red.
I am trying to match plots I make in R to plots I make in python using matplotlib.
The current code I use does not match the custom colors I want to use correctly. What can I change to get this to work correctly?
My main concern is matching the colour of the lines.
I am trying to use scale fill manual. This changes the colours but not in the way I want.
ggplot(data = reactor.summarised.ci, aes(x=standard_time, y=value, group =
group, colour=group)) +
geom_line(size = 0.25)+
geom_ribbon(aes(x = standard_time, ymin = lower.ci.od, ymax = upper.ci.od),
show.legend =FALSE, alpha =0.2, colour = NA)+
ylab("O.D.")+
xlab("Time (min)")+
xlim(0, 350)+
ggtitle('OD Over Time in in Bioreactor 1.02 before adjustment')+
theme(plot.title = element_text(hjust = 0.5))+
scale_fill_manual(values=c("#1f77b4", "#ff7f0e", "#2ca02c", '#d62728'))+
newtheme
newtheme is defined as follows:
newtheme <- theme_classic()+
theme(plot.title = element_text(hjust = 0.5))
I want to assign the following colours to the figure legend, ribbon and line.
(ReactorA = "#1f77b4",
ReactorB = "#ff7f0e",
ReactorC = "#2ca02c",
Reactor '#d62728')
current plot generated
You are mapping group to color not fill. Therefore you have to use scale_color_manual to adjust the color of the lines. Try this:
ggplot(data = reactor.summarised.ci, aes(x=standard_time, y=value, group =
group, colour=group)) +
geom_line(size = 0.25)+
geom_ribbon(aes(x = standard_time, ymin = lower.ci.od, ymax = upper.ci.od),
show.legend =FALSE, alpha =0.2, colour = NA)+
ylab("O.D.")+
xlab("Time (min)")+
xlim(0, 350)+
ggtitle('OD Over Time in in Bioreactor 1.02 before adjustment')+
theme(plot.title = element_text(hjust = 0.5)) +
scale_color_manual(values=c("reactorA" = "#1f77b4", "reactorB" = "#ff7f0e", "reactorC" = "#2ca02c", "reactorD" = '#d62728'))+
newtheme
I'm trying to plot a two "y" axis, the first one with "soil water content" in % (geom_line() ) and a geom_bar() with precipitation data. The problem is the precipitation chart. I need to "reverse" the plot.
I have this chart now:
and I need the soil water content time series as image above but precipitation as following image
Transforming the data do not solve the problem since i can not transform the bar plot for visualize it form upside down since the data are bars not points. Overmore when i reverse the plot both axis turn reverse
the "hum_melt10" data frame is a data frame with 3 columns: fecha = date (daily), value = water content (%) and variable = if the data is from a probe o from a model
the "pp_melt" data frame is a data frame with 3 columns: fecha = date (daily), value = cm of precipitation for each day and variable = if the water is from precipitation or irrigation
gpp = ggplot() +
geom_line(data = hum_melt10,aes(x = fecha, y = value, color = variable), size = 1.0) +
xlab("Fecha") +
geom_bar(data = pp_melt, aes(x = fecha, y = value / 20, fill = variable), stat="identity",position = 'dodge', na.rm = TRUE) +
scale_y_continuous(name = "Contenido de agua (%)",sec.axis = sec_axis(~.*20, name = "pp y riego (cm)")) +
scale_x_date(breaks = '2 month', labels = fecha, date_labels = '%b %y') +
theme(plot.title = element_text(lineheight=.8, face="bold", size = 20)) +
theme_bw() + theme( panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), axis.line = element_line(colour = "black"), aspect.ratio = 0.3)
Thank you!
Agreeing with #dmp, the use of sec_axis only adds the labels to the right; if you want to flip how it looks in the plot, you need to either
Use scale_y_reverse(), which will flip everything;
Manually flip the series in the aesthetic; or
Manually flip the series in the data itself.
Since you only want to reverse one of the data series and not all of them, #1 is out. #3 does work, though you'll still need to modify the call to sec_axis, so I'll keep it simple with doing just #2.
library(ggplot2)
mt <- transform(mtcars, rn = 1:nrow(mtcars))
ggplot(mt) +
geom_bar(aes(x = rn, y = drat), stat = "identity") +
geom_line(aes(x = rn, y = disp/100), stat = "identity", color = "red", size = 1) +
scale_y_continuous(sec.axis = sec_axis(~ . * 100))
Flipping just the red line, we change both how it is defined in the aesthetic (though it could be changed in the frame itself) and sec_axis.
ggplot(mt) +
geom_bar(aes(x = rn, y = drat), stat = "identity") +
geom_line(aes(x = rn, y = 5 - disp/100), stat = "identity", color = "red", size = 1) +
# changes: ^^^ vvv
scale_y_continuous(sec.axis = sec_axis(~ (5 - .) * 100))
(It's important to remember that the flipping point (5 in the example above) is based on the main-axis scale, not the new data.)
Without testing, I suspect the fix for your code would be something like this (where 9 is inferred from the plot).
gpp = ggplot() +
geom_line(data = hum_melt10,aes(x = fecha, y = value, color = variable), size = 1.0) +
xlab("Fecha") +
geom_bar(data = pp_melt, aes(x = fecha, y = 9 - value / 20, fill = variable), stat="identity",position = 'dodge', na.rm = TRUE) +
# changes: ^^^ vvv
scale_y_continuous(name = "Contenido de agua (%)", sec.axis = sec_axis(~(9 - .)*20, name = "pp y riego (cm)")) +
scale_x_date(breaks = '2 month', labels = fecha, date_labels = '%b %y') +
theme(plot.title = element_text(lineheight=.8, face="bold", size = 20)) +
theme_bw() + theme( panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), axis.line = element_line(colour = "black"), aspect.ratio = 0.3)
I am trying to plot two flows and one rainfall data in one graph. I have broke it up into top and bottom parts as shown in the following pic. Here I have two issues with this plots and spent ages but cannot solve it.
Why the observed flow always in black, even I have set it up as blue? Did I accidentally used some other arguments to overwrite it?
The most importantly is, how do I able to add a legend for the bottom plot? I tried many different codes but they don't seem to work for me.
x = data.frame(date = Date, rain = Obs_rain, obsflow = Obs_flow,simflow=Sim_flow)
g.top <- ggplot(x, aes(x = date, y = rain, ymin=0, ymax=rain)) +
geom_linerange() +
scale_y_continuous(trans = "reverse") +
theme_bw() +
theme(plot.margin = unit(c(1,5,-30,6),units="points"),
axis.title.y = element_text(vjust =0.3)) +
labs(x = "Date",y = "Rain(mm)")
g.bottom <- ggplot(x, aes(x = date, y = obsflow, ymin=0, ymax=obsflow), colour = "blue",size=0.5) +
geom_linerange() + #plot flow
geom_linerange(aes(y = simflow, ymin=0, ymax=simflow), colour = "red", size =0.5)+
labs(x = "Date", y = "River flow (ML/day)") +
theme_classic() +
theme(plot.background = element_rect(fill = "transparent"),
plot.margin = unit(c(2,0,1,1),units="lines"))
grid.arrange(g.top,g.bottom, heights = c(1/5, 4/5))
Update:
I have resolved the issue with blue line colour. I accidently put arguments in the wrong place. But I'm still struggling with the legend.
g.bottom <- ggplot(x, aes(x = date, y = obsflow, ymin=0, ymax=obsflow)) +
geom_linerange(colour = "blue",size=0.5) + #plot flow
As an explanation of what #pierre means... turn your data from "wide" to "long" format using reshape2::melt, so that the flow type for each date is in one column flow_type, and the value is another (flow_val). Then you specify flow_type as the grouping variable with which to assign colour:
require(reshape2)
x.melted <- melt(x, id.vars = c("date", "rain"), variable.name="flow_type",
value.name="flow_val")
g.bottom <- ggplot(x.melted, aes(x = date),size=0.5) +
geom_linerange(aes(ymin=0, ymax=flow_val, colour=flow_type)) + #plot flow
labs(x = "Date", y = "River flow (ML/day)") +
theme_classic() +
theme(plot.background = element_rect(fill = "transparent"),
plot.margin = unit(c(2,0,1,1),units="lines"),
legend.position="bottom") +
scale_colour_manual(guide = guide_legend(title = "Flow Type"),
values = c("obsflow"="blue", "simflow"="red"))