Adding a legend entry for geom_segment - r

In the chart below, I would like to include an item in the legend for the blue reference line, which for the sake of this example, we can call "Arbitrary Line". Can anyone provide me a solution for getting that into the legend? Note that the final plot must be rendered in plotly.
library(tidyverse)
library(plotly)
dat <- data.frame(peeps= c("Bill", "Bob", "Becky"),
vals = c(10, 15, 12),
label = c("8% Fake", "12% Pizza", "45% Becky"),
grp = c("Bears", "Bears", "Mongoose") %>% as.factor)
p1 <- dat %>%
ggplot(aes(x = peeps, y = vals, fill = grp)) +
geom_bar(stat = "identity") +
geom_segment(aes(x = 0.55, xend = 3.45, y = 5, yend = 5), color = "blue") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip()
ggplotly(p1) %>%
layout(legend = list(orientation = "h",
xanchor = "center",
y = -0.15,
x = 0.5))

Try to add:
scale_fill_manual(name = "", values="blue", label="Arbitrary Line")

Related

Error bar sizing skewed when using plotly

I have a chart which has an error bar on it:
However, when I put the chart inside a plotly wrapper, the error bar sizing gets messed up, as shown below:
Does anyone have a solution for keeping the error bar width the same size as the bar, as shown in plot 1, but while keeping the plot rendering with plotly?
library(tidyverse)
library(plotly)
dat <- data.frame(peeps= c("Bill", "Bob", "Becky"),
vals = c(10, 15, 12),
goals = c(8, 13, 10),
grp = c("Bears", "Bears", "Mongoose") %>% as.factor)
p1 <- dat %>%
ggplot(aes(x = peeps, y = vals, fill = grp)) +
geom_bar(stat = "identity") +
geom_errorbar(data = dat,
aes(ymin = goals, ymax = goals),
color = "blue",
size = 1,
linetype = 1) +
scale_y_continuous(expand = c(0, 0)) +
coord_flip()
p1
ggplotly(p1) %>%
layout(legend = list(orientation = "h",
xanchor = "center",
y = -0.15,
x = 0.5))
Using geom_segment() instead of geom_errorbar() is a work-around for this problem.
dat <- data.frame(peeps= c("Bill", "Bob", "Becky") %>% as.factor,
vals = c(10, 15, 12),
goals = c(8, 13, 10),
grp = c("Bears", "Bears", "Mongoose"),
rowid = 1:3)
p1 <- ggplot(data = dat, aes(x = peeps, y = vals, fill = grp, order = rowid)) +
geom_col() +
geom_segment(aes(
x = as.numeric(peeps)-0.45,
xend = as.numeric(peeps)+0.45,
y = goals, yend = goals),
color = "blue",
size = 1) +
scale_y_continuous(expand = c(0, 0)) +
coord_flip()
ggplotly(p1) %>%
layout(legend = list(orientation = "h",
xanchor = "center",
y = -0.15,
x = 0.5))

How to: Two horizontal Barplots "on top of eachother"

I have a data frame with: Fail [3,3,3,1] and Pass [50,40,50,10]
I just want to make a barplot of Fail and Pass
b_f <- barplot(dat_record$Fail[1], horiz = TRUE, ylab = "FAIL", las = 2, col = "red", xlim = c(0,200))
b_p <- barplot(dat_record$Pass[2], horiz = TRUE, ylab = "PASS", las = 2, col = "green", xlim = c(0,200))
How can i put this two barplots on top of eachother in one graphic/diagram, like this:
And second question:
How can i do this properly with ggplot2? I tried it out, but i always failed with:
ggplot(dat_failpass, aes = (x = fail, fill = "red")+
geom_bar(position = "dodge")+
coord_flip()
Can someone answer me this two question or can you give me any tipps? I'm new into this.
Thank you.
Since you want just the first value of the vectors "Fail" and "Pass" value, this code chunk must plot what you want:
library(ggplot2)
fail = c(3, 3, 3, 1)
pass = c(50, 40, 50, 10)
df = data.frame(value = c(fail[1], pass[1]), label = c('Fail', 'Pass'))
ggplot(df, aes(x = label, y = value)) +
geom_bar(stat = 'identity', position = 'stack') +
coord_flip() +
labs(y = 'Count') +
theme(axis.title.y = element_blank())
Here is the output:
Let us know if this solution solved your problem.
Using your data in this format, here the code for plot:
library(tidyverse)
#Data
df <- structure(list(Fail = c(3, 3, 3, 1), Pass = c(50, 40, 50, 10)), class = "data.frame", row.names = c(NA,
-4L))
Code:
#Reshape and plot
df %>% pivot_longer(cols = everything()) %>%
#Plot
ggplot(aes(x=name,y=value))+
geom_bar(stat = 'identity',fill='gray')+
coord_flip()+
theme_bw()
Output:

How make "bold" data labels in GGPubr?

I want bold values inside ggbarplot, but i really don't know how. yscale has to be "percent"
x <- pierwsze %>%
group_by(treatment_groups,sex) %>%
count() %>%
ggpubr::ggbarplot(
x = "treatment_groups",
fill = "sex",
y = "n",
label = TRUE, lab.col = "black", lab.vjust = 1.2,
position = position_fill(),
palette = get_palette(palette = "Oranges",5)
)+
labs(x="Treatment Group",y="Proportion",fill="Sex")+
yscale("percent",.format = TRUE)+
font("xy.text",size=10)
Here is a solution for printing labels in bold.
q <- ggplot_build(x)
x + geom_text(data=q$data[[2]], aes(x=x, y=y, label=label),
fontface="bold", vjust=1.2)

ggplot custom legend instead of default

I've searched and tried a bunch of suggestions to be able to display a custom legend instead of the default one in a grouped scatter ggplot. I've tried this and this and following this among others.
For instance, let's say I have a df like this one:
df = data.frame(id = c("A", "A", "B", "C", "C", "C"),
value = c(1,2,1,2,3,4),
ref = c(1.5, 1.5, 1, 2,2,2),
min = c(0.5, 0.5, 1,2,2,2))
and I want to display the values of each id as round dots, but also put the reference values and minimum values for each id as a differently shaped dot, as follows:
p = ggplot(data = df) +
geom_point(aes(x = id, y = value, color = factor(id)), shape = 19, size = 6) +
geom_point(aes(x = id, y = ref, color = factor(id)), shape = 0, size = 8) +
geom_point(aes(x = id, y = min, color = factor(id)), shape = 2, size = 8) +
xlab("") +
ylab("Value")
#print(p)
Now all is fine, but my legend doesn't add anything to the interpretation of the plot, as the X axis and colors are enough to understand it. I know I can remove the legend via theme(legend.position = "none").
Instead, I would like to have a legend of what the actual shapes of each dot represent (e.g., filled round dot = value, triangle = min, square = ref).
Among trying to manually set the scale values via scale_fill_manual and something along those lines
override.shape = shapes$shape
override.linetype = shapes$pch
guides(colour = guide_legend(override.aes = list(shape = override.shape, linetype = override.linetype)))...
....
I've also tried making a secondary plot, but not display it, using something suggested in one of the links pasted above:
shapes = data.frame(shape = c("value", "reference", "minimum"), pch = c(19,0,2), col = c("gray", "gray", "gray"))
p2 = ggplot(shapes, aes(shape, pch)) + geom_point()
#print(p2)
g_legend <- function(a.gplot){
tmp <- ggplot_gtable(ggplot_build(a.gplot))
leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
legend <- tmp$grobs[[leg]]
return(legend)
}
legend <- g_legend(p2)
library(gridExtra)
pp <- arrangeGrob(p1 ,legend,
widths=c(5/4, 1/4),
ncol = 2)
but then I get the error:
> legend <- g_legend(p2)
Error in tmp$grobs[[leg]] :
attempt to select less than one element in get1index
for which I did not find a working solution.. so yeah.. any suggestion on how I could only show a legend related to the different dot shapes would be welcome.
Thank you
You can manually build a shape legend using scale_shape_manual:
library(ggplot2)
ggplot(data = df) +
geom_point(aes(x = id, y = value, color = factor(id), shape = 'value'), size = 6) +
geom_point(aes(x = id, y = ref, color = factor(id), shape = 'ref'), size = 8) +
geom_point(aes(x = id, y = min, color = factor(id), shape = 'min'), size = 8) +
scale_shape_manual(values = c('value' = 19, 'ref' = 0, 'min' = 2)) +
xlab("") +
ylab("Value")
Created on 2020-04-15 by the reprex package (v0.3.0)
But a better way to do this would be to reshape the df to a long format, and map each aes to a variable:
library(dplyr)
library(tidyr)
df %>%
pivot_longer(-id) %>%
ggplot() +
geom_point(aes(x = id, y = value, color = factor(id), shape = name, size = name)) +
scale_shape_manual(values = c('value' = 19, 'ref' = 0, 'min' = 2)) +
scale_size_manual(values = c('value' = 6, 'ref' = 8, 'min' = 8)) +
xlab("") +
ylab("Value")
Created on 2020-04-15 by the reprex package (v0.3.0)
To remove the legend for the color use guide_none():
library(tidyr)
library(ggplot2)
df %>%
pivot_longer(-id) %>%
ggplot() +
geom_point(aes(x = id, y = value, color = factor(id), shape = name, size = name)) +
scale_shape_manual(values = c('value' = 19, 'ref' = 0, 'min' = 2)) +
scale_size_manual(values = c('value' = 6, 'ref' = 8, 'min' = 8)) +
guides(color = guide_none()) +
xlab("") +
ylab("Value")
Created on 2020-04-16 by the reprex package (v0.3.0)
Data:
df = data.frame(id = c("A", "A", "B", "C", "C", "C"),
value = c(1,2,1,2,3,4),
ref = c(1.5, 1.5, 1, 2,2,2),
min = c(0.5, 0.5, 1,2,2,2))
You can tidy your data first using tidyr, and then map the aes shape to the new variable
library(tidyr)
df2 <- pivot_longer(df, -id)
ggplot(data = df2) +
geom_point(aes(x = id, y = value, shape = name), size = 6) +
xlab("") +
ylab("Value")

Use geom_curve() to make an arrow without x and xend argument

I have a seemingly small problem. I want to plot an arrow with geom_curve() on top of a bar chart within ggplot. The goal is to point out a single value from the bar chart.
In every other case, in order to plot the arrow with geom_curve(), we need to fill in the arguments x, xend, y and x yend. However, when plotting a bar chart with geom_bar(), theaes(x = x) is not specified. My question is how are we able to plot the arrow, even without specifying the x arguments.
Some sample code can be found below. How to use geom_segment() can be found here. Any help would be much appreciated
library(tidyverse)
library(tidyquant)
tbl <- tibble(
Var1 = c(0, 2, 4, 6, 8),
pct = c(rep(0.2, 5))
) %>%
mutate(Var1 = Var1 %>% as_factor() %>% fct_rev())
tbl %>%
ggplot(aes(x = "", y = pct, fill = Var1)) +
geom_bar(stat = "identity") +
coord_flip() +
scale_fill_tq() +
geom_text(aes(label = if_else(Var1 == 0, "20 %", "")), nudge_y = -0.025, nudge_x = 0.55, size = 5, color = "#2C3E50")
Are you looking for something like that ? Or did I misunderstand your question ?
In ggplot2, even if you don't have x axis values, each bar of a bargraph can be associated to a number starting at 1.
So, if you have two bar on your graph, their x position are 1 and 2.
Here, you have only one bar, you can use that to add your arrow slight up to 1 (here I choose 1.50)
tbl %>%
ggplot(aes(x = "", y = pct, fill = Var1)) +
geom_bar(stat = "identity") +
coord_flip() +
#scale_fill_tq() +
geom_text(aes(label = if_else(Var1 == 0, "20 %", "")), nudge_y = -0.025, nudge_x = 0.55, size = 5, color = "#2C3E50")+
geom_segment(x = 1.50, xend = 1.50, y = 0.1, yend = 0.75, arrow = arrow(length = unit(0.03, "npc")))
Does it answer your question ?
Thanks to #dc37, I got the arrow at the right place and pointing to a specific part of the bar chart.
tbl %>%
ggplot(aes(x = "", y = pct, fill = Var1)) +
geom_bar(stat = "identity") +
coord_flip() +
geom_text(aes(label = if_else(Var1 == 0, "20 %", "")), nudge_y = -0.05, nudge_x = 0.51, size = 5, color = "#2C3E50") +
geom_curve(aes(x = 1.51, xend = 1.46, y = 0.1, yend = 0.05), curvature = 1, color = "#2C3E50", arrow = arrow(length = unit(0.02, "npc")))

Resources