Fairly new to R so forgive me if this is a simple question. I have created a graph which tracks a loss ratio percentage by data provider. I assign the "data provider" lines colour using scale_colour_brewer 'blue'. In a previous iteration I had used scale_colour_manual to assign a colour to a data provider, however this can no longer be used as the data providers are now variables in the code using an IF statement to only include in the Shiny report if assigned a 1 earlier in the code.
I have tried to put a Horizontal line at .85 which I am trying to get the colour to be red. The scale_colour_brewer 'blue' portion of the code seems to overwrite the 'red' line, meaning it is a thick blue line and has the name 'red' in the legend. How do I correct this? Example code below:
LR_Graph_Plot <- ggplot() +
geom_hline(aes(yintercept = 0.85, color ="red"), size = 1.25) +
geom_line(data = LR_Graph(), aes(x = YM1_DATE, y = ELR, group = Data.Provider, color = Data.Provider), size = 0.75) +
# geom_hline(aes(yintercept = 0)) +
scale_colour_brewer("Blues") +
labs(y = "Loss Ratio (%)") +
ggtitle("Earned Loss Ratio: Loss Ratio Monthly split by Data Provider") +
scale_y_continuous(labels = scales ::percent) +
scale_x_date(breaks = "months", date_labels = "%Y-%m") +
theme_bw() +
theme(axis.title.x = element_blank(), legend.title = element_blank(), panel.border = element_blank(),
axis.line.y = element_line(color='black'), axis.line.x = element_line(color='black'),
legend.position = "right" , axis.text.x = element_text(angle = 90)) +
theme(
panel.background = element_rect(fill="#cccccc", color="#000000",size = 2, linetype = "solid"),
panel.grid.major = element_line(size = 0.5, linetype = "solid", colour = "white"),
panel.grid.minor = element_line(size = 0.5,linetype = "solid", colour = "white")
)
ELR_Graph_Plot <- ggplotly(LR_Graph_Plot)
Apologies if this is not clear or has been asked before. I'm fairly new to coding.
Move the color assignment out of the aesthetic mapping aes(). Then the line uses a fixed color and not the provided color scale.
Your line geom_hline(aes(yintercept = 0.85, color ="red"), size = 1.25) should be geom_hline(aes(yintercept = 0.85), color ="red", size = 1.25)
I need to create a ggplot that is a column plot overlayed with a line plot. The line plot shows mean values, while the column plot shows how the mean values relate to benchmark values. I've managed to create two separate plots in ggplot, but I'm having trouble combining them.
My line plot looks like this:
And is created using this code:
benchMarkLine <- ggplot(UEQScores, aes(x=Scale, y=Score, group=1)) +
geom_line(size = 1.4, colour = "black") +
geom_point(size = 2.4, colour = "black") +
scale_y_continuous(name = "Score", breaks = seq(0, 2.5, 0.25), limits = c(0, 2.5)) +
scale_x_discrete(name = "Scale") +
ggtitle("Mean Scores") +
theme_bw() + # Set black and white theme +
theme(plot.title = element_text(hjust = 0.5, size=10), # Centre plot title
panel.grid.major = element_blank(), # Turn off major gridlines
panel.grid.minor = element_blank(), # Turn off minor gridlines
axis.title.x = element_text(size=10),
axis.text.x = element_text(angle=30, vjust=0.6),
axis.title.y = element_text(size=10))
benchMarkLine
My Column plot looks like this:
And was created with the following code:
benchmarkColPlot <- ggplot(benchmark_long, aes(x=factor(Scale, scaleLevels), y=value, fill=factor(cat, bmLevels))) +
geom_col(position="fill") +
scale_fill_manual(values = bmColours) +
scale_y_continuous(name = "Score", breaks = seq(-1.0, 1.0, 0.25), limits = c(-1, 1)) +
scale_x_discrete(name = "Scale") +
ggtitle("Benchmark Scores") +
theme_bw() + # Set black and white theme +
theme(plot.title = element_text(hjust = 0.5, size=10), # Centre plot title
panel.grid.major = element_blank(), # Turn off major gridlines
panel.grid.minor = element_blank(), # Turn off minor gridlines
axis.title.x = element_text(size=10),
axis.text.x = element_text(angle=30, vjust=0.6),
axis.title.y = element_text(size=10),
legend.title = element_blank())
benchmarkColPlot
How can I combine these two? I tried inserting geom_line(UEQScores, aes(x=Scale, y=Score, group=1)) + above geom_col(position="fill") + in the column plot code, but I just get the following error:
Error: `mapping` must be created by `aes()`
How do I combine these two plots?
OK, I've given up on this - I just created the chart in Excel as it seems to be a bit easier for what I'm doing here.
How can I insert annotations outside the plot?
I want to add a note on top of the first bar to signal that it continues e.g. up to 1000. If I use annotate, the note won't go outside the plot. (Note that I am using coord_cartesian to limit the y axis to 100.)
Here is my code.
plot <- ggplot() +
geom_crossbar(data=GHG, aes(x=Study, y=Avg, ymin=Min, ymax=Max),
fill="white", width=0.3) +
coord_cartesian(ylim=c(0, 100), clip="off") +
labs(x="", y="g CO2-eq.") +
annotate("text", x=1, y=150, label=c("150"), vjust=-1) +
theme(legend.position = "bottom",
axis.text.x = element_text(angle=0, vjust=1, hjust=0.5),
panel.grid.major.x= element_blank(),
panel.grid.minor = element_blank(),
plot.margin = unit(c(1,3,1,1),"lines"))
And here is the chart:
One strategy is to use a secondary axis and the labels to annotate your bar.
This is a bit tricky, because only continuous scales can have a secondary axis.
I used the following data.frame for test purpose:
GHG <- data.frame(Avg = c(50, 37, 62), Min = c(10, 25, 25), Max = c(1000, 50, 80), Study = c("A", "B", "C"))
The code:
ggplot() +
geom_crossbar(data=GHG, aes(x=as.numeric(Study), y=Avg, ymin=Min, ymax=Max),
fill="white", width=0.3) +
coord_cartesian(ylim=c(0, 100), clip = "on") +
scale_x_continuous(position = "top",
breaks = 1:length(unique(GHG$Study)),
labels = c(1000, rep("", length(unique(GHG$Study)) - 1)),
sec.axis = sec_axis(~.,
breaks = 1:length(unique(GHG$Study)),
labels = rep("", length(unique(GHG$Study))))) +
labs(x="", y="g CO2-eq.") +
theme(legend.position = "bottom",
axis.text.x = element_text(angle=0, vjust=1, hjust=0.5),
panel.grid.major.x= element_blank(),
panel.grid.minor = element_blank(),
plot.margin = unit(c(1,3,1,1),"lines"),
axis.ticks.x.top = element_blank(),
axis.text.x.top = element_text(size = 14, color = "black", margin = margin(b = 5)))
Details:
The aes is slightly changed to allow for continuous scale: aes(x=as.numeric(Study), y=Avg, ymin=Min, ymax=Max)
In coord_cartesian(ylim=c(0, 100), clip = "on"): clip is set to on to clip the part of the bars that goes out of the plot area.
Add and configure the continuous scale for X on top: scale_x_continuous(position = "top",
Manually add breaks for each value of Study: breaks = 1:length(unique(GHG$Study)),
Label the first break with the text you want to add, the rest of the breaks has no text: labels = c("text", rep("", length(unique(GHG$Study)) - 1)),
Add a secondary axis to keep the ticks at the bottom. If you don't want them, this is not necessary: sec.axis = sec_axis(~.,
Manually set the breaks for the continuous scale: breaks = 1:length(unique(GHG$Study)),
And add blank labels to reproduce your example: labels = rep("", length(unique(GHG$Study))))) +
In the theme method, remove the ticks for the top axis: axis.ticks.x.top = element_blank(),
And finally customize the font, color and everything for the top label: axis.text.x.top = element_text(size = 14, color = "black", margin = margin(b = 5)))
This question already has answers here:
ggplot2 - jitter and position dodge together
(2 answers)
Closed 6 years ago.
I have a data which can be divaded via two seperators. One is year and second is a field characteristics.
box<-as.data.frame(1:36)
box$year <- c(1996,1996,1996,1996,1996,1996,1996,1996,1996,
1997,1997,1997,1997,1997,1997,1997,1997,1997,
1996,1996,1996,1996,1996,1996,1996,1996,1996,
1997,1997,1997,1997,1997,1997,1997,1997,1997)
box$year <- as.character(box$year)
box$case <- c(6.40,6.75,6.11,6.33,5.50,5.40,5.83,4.57,5.80,
6.00,6.11,6.40,7.00,NA,5.44,6.00, NA,6.00,
6.00,6.20,6.40,6.64,6.33,6.60,7.14,6.89,7.10,
6.73,6.27,6.64,6.41,6.42,6.17,6.05,5.89,5.82)
box$code <- c("L","L","L","L","L","L","L","L","L","L","L","L",
"L","L","L","L","L","L","M","M","M","M","M","M",
"M","M","M","M","M","M","M","M","M","M","M","M")
colour <- factor(box$code, labels = c("#F8766D", "#00BFC4"))
In boxplots, I want to display points over them, to see how data is distributed. That is easily done with one single boxplot for every year:
ggplot(box, aes(x = year, y = case, fill = "#F8766D")) +
geom_boxplot(alpha = 0.80) +
geom_point(colour = colour, size = 5) +
theme(text = element_text(size = 18),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.x = element_blank(),
legend.position = "none")
But it become more complicated as I add fill parameter in them:
ggplot(box, aes(x = year, y = case, fill = code)) +
geom_boxplot(alpha = 0.80) +
geom_point(colour = colour, size = 5) +
theme(text = element_text(size = 18),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.x = element_blank(),
legend.position = "none")
And now the question: How to move these points to boxplot axes, where they belong? As blue points to blue boxplot and red to red one.
Like Henrik said, use position_jitterdodge() and shape = 21. You can clean up your code a bit too:
No need to define box, then fill it piece by piece
You can let ggplot hash out the colors if you wish and skip constructing the colors factor. If you want to change the defaults, look into scale_fill_manual and scale_color_manual.
box <- data.frame(year = c(1996,1996,1996,1996,1996,1996,1996,1996,1996,
1997,1997,1997,1997,1997,1997,1997,1997,1997,
1996,1996,1996,1996,1996,1996,1996,1996,1996,
1997,1997,1997,1997,1997,1997,1997,1997,1997),
case = c(6.40,6.75,6.11,6.33,5.50,5.40,5.83,4.57,5.80,
6.00,6.11,6.40,7.00,NA,5.44,6.00, NA,6.00,
6.00,6.20,6.40,6.64,6.33,6.60,7.14,6.89,7.10,
6.73,6.27,6.64,6.41,6.42,6.17,6.05,5.89,5.82),
code = c("L","L","L","L","L","L","L","L","L","L","L","L",
"L","L","L","L","L","L","M","M","M","M","M","M",
"M","M","M","M","M","M","M","M","M","M","M","M"))
ggplot(box, aes(x = factor(year), y = case, fill = code)) +
geom_boxplot(alpha = 0.80) +
geom_point(aes(fill = code), size = 5, shape = 21, position = position_jitterdodge()) +
theme(text = element_text(size = 18),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.x = element_blank(),
legend.position = "none")
I see you've already accepted #JakeKaupp's nice answer, but I thought I would throw in a different option, using geom_dotplot. The data you are visualizing is rather small, so why not forego the boxplot?
ggplot(box, aes(x = factor(year), y = case, fill = code))+
geom_dotplot(binaxis = 'y', stackdir = 'center',
position = position_dodge())
I have a plot in ggplot that shows me for each category of "rating" the level of price in "bank" and "sistem". This is my code:
##fict
a<-c("rating1","rating2","rating3")
b<-c(1.2,1.2,1.3)
c<-c(1.6,1.4,1.6)
gg<-cbind('rating'=rep(a,2),'price'=c(b,c),'tipo'=rep(c("bank","sistem"),3))
gg<-as.data.frame(gg)
a<-rgb(red=150, green=191, blue=37, maxColorValue = 255)
b<-rgb(red=80, green=113, blue=14, maxColorValue = 255)
ggplot(gg, aes(x=tipo, y=price,width=1)) +
geom_bar(position='stack', stat='identity', fill=c(b,a), color='black') +
facet_wrap( ~ rating)+
theme_bw() + theme(axis.line = element_line(colour = "black"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.background = element_blank(),
strip.background = element_rect(colour = 'white', fill = 'white', size = 3),
axis.title.y=element_text(vjust=0.19),
axis.title.x=element_text(vjust=0.19)
#strip.text.x = element_text(colour = 'red', angle = 45, size = 10, hjust = 0.5, vjust = 0.5, face = 'bold')
) + xlab("My x label") +
ylab("My y label") +
labs(title = 'difference')
This code generates my plot.
I'd like to change 3 things:
I'd like that the labels rating shows in the bottom
I'd like that the "bank" and "sistem" labels disappear and change it with the legend with colors for bank and sistem.
If it's possible also put the legend under the x-axis title in horizontal way
Thank you
Upgrade comment to an answer.
library(ggplot2)
# your data - tweaked the code - there is no need to cbind within data.frame
# and names do not need to be in quotes
gg <- data.frame(rating=rep(c("rating1","rating2","rating3"),2),
price=c(c(1.2,1.2,1.3),c(1.6,1.4,1.6)),
tipo=rep(c("bank","sistem"),3))
a <- rgb(red=150, green=191, blue=37, maxColorValue = 255)
b <- rgb(red=80, green=113, blue=14, maxColorValue = 255)
# Plot
# use position dodge to get the bars side-by-side
# theme_classic removes grid lines and uses theme_bw()
# scale_fill_manual to manually specify the colours - by using fill = tipo in the
# aesthetic call of ggplot a legend will be generated
# scale_y_continuous - using expand starts the axis at exactly zero
ggplot(gg, aes(x=rating, y=price, fill=tipo)) +
geom_bar(position='dodge', stat='identity', color='black') +
theme_classic() +
scale_fill_manual(values = c(b,a)) +
scale_y_continuous(limit=c(0,2), expand=c(0,0)) +
labs(title = 'difference', x = "My x label", y = "My y label") +
theme(
axis.title.y=element_text(vjust=0.19),
axis.title.x=element_text(vjust=0.19) ,
legend.position = "bottom",
legend.title=element_blank())