gghighlight (R): Labeling bar charts - r

Alright, after a long silent read along, here's my first question. I am trying to add corresponding labels of unhighlighted items for a grouped barplot. When I insert gghighlight in front of the geom_text I get the following plot:
library(tidyverse)
library(gghighlight)
df <- data.frame (group = c("A", "A", "B", "B", "C", "C"),
value = c("value_1", "value_2","value_1", "value_2","value_1", "value_2"),
mean = c(1.331, 1.931, 3.231, 3.331, 4.631, 3.331)
)
ggplot(data = df, aes(x = group, y = mean, fill = value)) +
geom_bar(stat = "identity", position = "dodge") +
gghighlight(group != "B",
label_key = group
) +
geom_text(aes(label = round(mean, digits = 2)),
stat= "identity",
vjust = -.5,
position = position_dodge(width = .9)
)
If I move gghightlight behind the geom_text I get the following plot:
ggplot(data = df, aes(x = group, y = mean, fill = value)) +
geom_bar(stat = "identity", position = "dodge") +
geom_text(aes(label = round(mean, digits = 2)),
stat= "identity",
vjust = -.5,
position = position_dodge(width = .9)
) +
gghighlight(group != "B",
label_key = group)
Is there a way to label the unhighligthed bars like the highlighted ones?
Thanks in advance.
############## EDIT ###########
Besides graying out certain columns (see #TarJae's answer), there is also the possibility to make them transparent (essential parts are from this post: ggplot transparency on individual bar):
subset_df <- df %>%
mutate(alpha.adj = as.factor(ifelse(group != "B", 1, 0.6)))
ggplot(data = subset_df, aes(x = group, y = mean, fill = value, alpha=factor(alpha.adj))) +
geom_bar(stat = "identity", position = "dodge") +
geom_text(aes(label = round(mean, digits = 2)),
stat= "identity",
vjust = -.5,
position = position_dodge(width = .9)
) +
scale_alpha_manual(values = c("0.6"=0.6, "1"=1), guide='none')
[]

Are you looking for this?
This is a solution without using gghighlight package:
library(tidyverse)
subset_df <- df %>%
mutate(highlight = if_else(group != "B", mean, NA_real_))
ggplot(data = subset_df, aes(x = group, y = mean, group=value)) +
geom_col(fill = 'grey', alpha = 0.6, position = 'dodge') +
geom_col(aes(y = highlight, fill = value), position = 'dodge') +
geom_text(aes(group, label = round(mean, digits = 2)),
position = position_dodge(width = 1))

This is a solution with the gghighlight package and some limited hacky code.
When reading the vignette, I noticed that the author of the package "filters out" the data that are not highlighted. You can see that if you save your highlighted plot in p_h and then look at p_h$data, the values for group B have disappeared.
library(tidyverse)
library(gghighlight)
p_h <- ggplot(data = df, aes(x = group, y = mean, fill = value)) +
geom_bar(stat = "identity", position = "dodge") +
gghighlight(group != "B",
label_key = group) +
geom_text(aes(label = round(mean, digits = 2)),
stat= "identity",
vjust = -.5,
position = position_dodge(width = .9))
> p_h$data
group value mean
1 A value_1 1.331
2 A value_2 1.931
5 C value_1 4.631
6 C value_2 3.331
If we re-insert the data (after the call to gghighlight() has removed them), then geom_text() will be able to find the means for group B again.
One can "recover" the data and re-insert them with the following code:
### create a ggplot object with the original complete data
### you could check that with p_to_copy_data$data
p_to_copy_data <- ggplot(data = df)
### copy the complete data to your highlighted plot data section
p_h$data <- p_to_copy_data$data
p_h
This yields the following graph:

Related

R ggplot2 : geom_jitter and fill, problem to have the dots on the right boxplot

Here's my R code
ggplot(dat = Table, aes(x = Group, y = value, fill = Type)) +
geom_boxplot(alpha=0.08)+
geom_jitter()+
scale_fill_brewer(palette="Spectral")+
theme_minimal()
Like you can see the dots are in the middle of the boxplots. What can I add in geom_jitter to have each point in the righ boxplot and not in the middle like this ? I also tried geom_point, it gave the same result !
Thanks to the help now It works, but I wanted to add a line to connect the dots and I got this.. can someone tell how to really connect the dots with lines
I think if you group by interaction(Group, Type) and use position_jitterdodge() you should get what you're looking for.
ggplot(mtcars, aes(as.character(am), mpg, color = as.character(vs),
group = interaction(as.character(vs), as.character(am)))) +
geom_boxplot() +
geom_jitter(position = position_jitterdodge()) # same output with geom_point()
Edit - here's an example with manual jittering applied to data where the each subject appears once in each Group.
I looked for a built-in way to do this, and this answer comes close, but I couldn't get it to work in terms of using position_jitterdodge with position defined by the groups of Group/Type, but line grouping defined by id alone and not by Group/Type. Both aesthetics (position adjustment and series identification) rely on the same group parameter, but they each need a different value for it.
Table = data.frame(id = 1:4,
value = rnorm(8),
Group = rep(c("a","b"), each = 4),
Type = c("1", "2"))
library(dplyr)
Table %>%
mutate(x = as.numeric(as.factor(Group)) +
0.2 * scale(as.numeric(as.factor(Type))) +
rnorm(n(), sd = 0.06)) %>%
ggplot(aes(x = Group, y = value, fill = Type, group = interaction(Group, Type))) +
geom_boxplot(alpha=0.2)+
geom_point(aes(x = x)) +
geom_line(aes(x = x, group = id), alpha = 0.1) +
scale_fill_brewer(palette="Spectral")+
theme_minimal()
Best to use position_dodge instead if you want them to line up:
library(ggplot2)
Table <- tibble::tibble(
Group = rep(c("A", "B"), each = 20),
Type = factor(rep(c(1:2, 1:2), each = 10)),
value = rnorm(40, mean = 10)
)
ggplot(dat = Table, aes(x = Group, y = value, fill = Type)) +
geom_boxplot(alpha=0.08)+
geom_point(position = position_dodge(width = 0.75))+
scale_fill_brewer(palette="Spectral")+
theme_minimal()
To add a line, make sure group = ID goes in both the geom_point and geom_line calls:
library(ggplot2)
Table <- tibble::tibble(
Group = rep(c("A", "B"), each = 20),
Type = factor(rep(c(1:2, 1:2), each = 10)),
ID = factor(rep(1:20, times = 2)),
value = rnorm(40, mean = 10)
)
ggplot(dat = Table, aes(x = Group, y = value, fill = Type)) +
geom_boxplot(alpha = 0.08) +
geom_point(aes(group = ID), position = position_dodge(width = 0.75))+
geom_line(aes(group = ID), position = position_dodge(width = 0.75), colour = "grey")+
scale_fill_brewer(palette = "Spectral") +
theme_minimal()

Barplot in ggplot - dodge position + counting

Hey I have the following code:
df = data.frame(Type = c("A", "B", "A", "A", "B"), FLAG = c(1, 1, 0, 1, 0))
df
ggplot(df, aes(x = Type)) + geom_bar(stat = "count", aes(fill = factor(FLAG)), position = "dodge") + coord_flip() + stat_count(geom = "text", colour = "white", size = 3.5,
aes(label = ..count..),position=position_stack(vjust=0.5)) + theme_bw()
but it doesnt work as I want. The graph is OK but instead displaying the total number of observations of each type I want to display the number of each flag (so instead 2 for "B" type I want to display 1 and 1 because for "B" we have 1 observation with FLAG 1 and 1 observations with FLAG 0). What should I change?
With the interaction between Type and FLAG the bars display the counts per groups of both.
ggplot(df, aes(x = interaction(Type, FLAG))) +
geom_bar(stat = "count",
aes(fill = factor(FLAG)), position = "dodge") +
coord_flip() +
stat_count(geom = "text",
aes(label = ..count..),
position=position_stack(vjust=0.5),
colour = "white", size = 3.5) +
theme_bw()
You could replace the stat_count() and geom_bar() with a little pre-processing with count() and geom_col(). Here is an example:
df %>%
janitor::clean_names() %>%
count(type, flag) %>%
ggplot(aes(type, n, fill = as.factor(flag))) +
geom_col(position = "dodge") +
geom_text(aes(label = n, y = n - 0.05), color = "white",
position = position_dodge(width = 1)) +
scale_y_continuous(breaks = 0:3, limits = c(0,3)) +
labs(fill = "flag") +
coord_flip() +
theme_bw()
The only thing janitor::clean_names() does is transform variable names, from uppercase and spaces to lowercase and underscores, respectively.

How to position labels on grouped bar plot columns in ggplot2

I am having trouble positioning percentage&count labels on a grouped barplot.
The labels are currently stacked together:
I think this is because I have been referring to an example code for a stacked barplot. I have tried adding position=position_dodge(width=1) to geom_textto unstack the labels, but I have gotten the following warning:
Warning: Ignoring unknown aesthetics: position
Don't know how to automatically pick scale for object of type PositionDodge/Position/ggproto/gg. Defaulting to continuous.
Error: Aesthetics must be valid data columns. Problematic aesthetic(s): position = position_dodge(width = 1).
Did you mistype the name of a data column or forget to add stat()?
Here is the code I have using the Titanic dataset:
data("titanic_train")
head(titanic_train, 6)
library(dplyr)
library(ggplot2)
titanic_train$Survived <- as.factor(titanic_train$Survived)
summary = titanic_train %>% group_by(Survived, Sex) %>% tally %>% mutate(pct = n/sum(n))
ggplot(summary, aes(x=Sex, y=n, fill=Survived)) + geom_bar(stat="identity", position="dodge") + geom_text(aes(label=paste0(sprintf("%1.1f", pct*100),"%\n", n)), colour="black")
How can I resolve this?
You can just add position = position_dodge(width = 1) to your geom_text call, but outside of aes. Your error was caused by trying to put position... inside aes.
library(dplyr)
library(ggplot2)
library(titanic)
ggplot(summary, aes(x = Sex, y = n, fill = Survived)) +
geom_bar(stat = "identity", position = "dodge") +
geom_text(aes(label = paste0(sprintf("%1.1f", pct * 100), "%\n", n)),
colour = "black",
position = position_dodge(width = 1)) +
coord_cartesian(ylim = c(0, 550))
I would like to share an example which you could replicate the same by using your data
data
df <- data.frame(
x = factor(c(1, 1, 2, 2)),
y = c(1, 3, 2, 1),
grp = c("a", "b", "a", "b")
)
plot
ggplot(data = df, aes(x, y, group = grp)) +
geom_col(aes(fill = grp), position = "dodge") +
geom_text(
aes(label = y, y = y + 0.05),
position = position_dodge(0.9),
vjust = 0
)

ggplot anotate when x values are characters

I would like to 'annotate' a text on the top right hand corner of ggplot2 bar chart that has character for x axis and numeric for y axis. All the documentation I see is that, to annotate a text, both x and y coordinates have to be given numeric value.
Here is an example chart:-
Here is the data frame
df1 <- data.frame( p=c("a","b","c","a","b","c"),
v=c(10,9,8,6,5,2),
u=c("aa","bb","cc","aa","bb","cc")
)
summarized data frame
df2 <- df1 %>% select(p, v) %>% group_by(p) %>% summarise_each(funs(sum))
bar plot
p <- ggplot(data = df2, aes(p, v, label = v)) +
geom_bar(stat = "identity", position = "dodge") +
geom_text(position = position_dodge(.9), vjust = -1, fontface = "bold", size = 5)
p
You should be able to do it just putting the location inside of aes(). This worked for me (unless I am misunderstanding your intent):
ggplot(data = df2, aes(p, v, label = v)) +
geom_bar(stat = "identity", position = "dodge") +
geom_text(position = position_dodge(.9), vjust = -1, fontface = "bold", size = 5) +
geom_text(aes(x = "c", y = 15, label = "Here I am"))

r annotate values above geometric bars

Consider this sample data.
df <- data.frame(
x = factor(c(1, 1, 2, 2)),
y = c(.1, .3, .2, .1),
grp = c("a", "b", "a", "b")
)
Now I create the graph using ggplot, and annotate it using geom_text()
ggplot(data = df, aes(x, y, fill = grp, label = y)) +
geom_bar(stat = "identity", position = "dodge") +
scale_y_continuous(limits=c(0,1)) +
geom_text(position = position_dodge(0.9))
How do I specify that all the text values align perfectly horizontal at the top of the graph window?
You can specify the aes(y=...) in geom_text. So, for the numbers at the top of the graph window you'll have
ggplot(data = df, aes(x, y, fill = grp, label = y)) +
geom_bar(stat = "identity", position = "dodge") +
geom_text(aes(y=Inf), position = position_dodge(0.9))
And you may want to chuck in a + ylim(0, 4) to expand the plot area.
To match the edited question:
ggplot(data = df, aes(x, y, fill = grp, label = y)) +
geom_bar(stat = "identity", position = "dodge") +
scale_y_continuous(limits=c(0,1)) +
geom_text(aes(y=0.9), position = position_dodge(0.9)) ## can specify any y=.. value

Resources