I would like to combine stacked with dodge style of a barplot in ggplot. I'm quite near it with this code:
dates_g <- as.Date(c("2020-03-30","2020-03-30", "2020-04-30","2020-04-30", "2020-05-30","2020-05-30"))
value_x <- c(1, 2, 4, 1.4, 3.2, 1.3)
value_y <- c(1.2, 3, 4.6, 1, 3, 1)
ID <- c("A", "B", "A", "B", "A", "B")
results <- data.frame(dates_g, value_x, value_y, ID)
barwidth = 13
bar_comparison <- ggplot() +
geom_bar(data = results[,c(1,2,4)],
mapping = aes(x=dates_g , y=value_x, fill=ID),
stat ="identity",
position = "stack",
width = barwidth) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
geom_bar(data = results[,c(1,3,4)],
mapping = aes(x=dates_g + barwidth + 0.01 , y=value_y, fill=ID),
stat ="identity",
position = "stack",
width = barwidth) +
xlab("Date") + ylab("Value (in millions)")
ggplotly(bar_comparison)
which gives as a result:
I'm still not happy about two things: I would like the date to be between the two bars (but this is a minor problem) and then I really would like to have, for each date, different colors for the two bars: for example I would like to have the left bar to be in a scale of green (dark green and light green) and the right one in a scale of blue (dark blue and light blue). is it possible?
This at least is a solution for the main question.
I would suggest to use facet_wrap.
Data preparation for this -> bring data in long format, Extract the month name of your date (I use lubridate for this), then plot with ggplot
library(lubridate)
results_long <- results %>%
pivot_longer(
cols = starts_with("value"),
names_to = "Names",
values_to = "Values"
) %>%
mutate(dates_name = parse_number(as.character(dates_g)),
dates_name = month(ymd(dates_g), label = TRUE))
ggplot(results_long, aes(x = Names, y = Values, fill = ID)) +
geom_bar(stat = 'identity', position = 'stack') + facet_grid(~ dates_name) +
theme_bw()
Related
I am having issues in preventing same factor from stacking on top of itself when plotting a barplot. Problem is that I don't know how to plot the unique values of such factor and i end up having it n times (n = times the factor is repeated) in the same plot. Here a nice example of the issue:
library("ggplot2")
mydata <- data.frame(var_one=rep(c("a", "b", "c", "d", "e"), 5), var_two=rep(c(1.5, 2, 2.2, 1.8, 1.2), 5))
dev.new()
ggplot(mydata, aes(x=var_one, y=var_two)) +
geom_bar(stat="identity", fill="lightcoral", alpha=.8, width=.4, color="black")
the goal is to have only one of the multiple stacked factors. How to do it? I also tried with geom_col, instead of geom_bar but it doesn't seem to solve the issue.
dev.new()
ggplot(mydata, aes(x=var_one, y=var_two)) +
geom_col(fill="lightcoral", alpha=.8, width=.4, color="black")
This is what i need:
mydata_mod <- data.frame(var_one=c("a", "b", "c", "d", "e"), var_two=c(1.5, 2, 2.2, 1.8, 1.2))
dev.new()
ggplot(mydata_mod, aes(x=var_one, y=var_two)) +
geom_bar(stat="identity", fill="lightcoral", alpha=.8, width=.4, color="black")
but the problem is the data structure that i am using is not in the format of mydata_mod but it is defined as mydata and i have to keep it that way. Ideas?
You could achieve your desired result by using stat_summary or by switching to stat="summary" in geom_bar to compute the sum on the fly:
library("ggplot2")
ggplot(mydata, aes(x = var_one, y = var_two)) +
stat_summary(
geom = "bar", fun = "sum",
fill = "lightcoral", alpha = .8, width = .4, color = "black"
)
ggplot(mydata, aes(x = var_one, y = var_two)) +
geom_bar(
stat = "summary", fun = "sum",
fill = "lightcoral", alpha = .8, width = .4, color = "black"
)
Another option is to wrangle the data:
library(dplyr)
library(ggplot2)
mydata %>%
group_by(var_one) %>%
summarise(sum = sum(var_two)) %>%
ggplot(aes(x = var_one, y=sum)) +
geom_col(fill="lightcoral", alpha=.8, width=.4, color="black")
The geom Texts labels are automatically in decreasing order instead of the data frame.
The question is concerning this part of the snippet "geom_text(aes(label = Freq)..."
Here you can clearly see the that the order is not followed by geom_text. But Frequency descreasing in all categories.
ggplot(df_beine_clan, aes(x = Var2, y = Freq, fill = Var1)) +
geom_bar(stat = "identity") +
geom_text(aes(label = Freq), vjust = 0, size = 5, nudge_y = 2, nudge_x = -0.5)
See Freq Order
How to command that the order should not be changed when rendered on the bar chart?
You could add position_stack like this:
library(ggplot2)
ggplot(df_beine_clan, aes(x = Var2, y = Freq, fill = Var1)) +
geom_bar(stat = "identity") +
geom_text(aes(label = Freq), position = position_stack(vjust = 0.5), size = 5)
Created on 2022-09-03 with reprex v2.0.2
Answering your question without having a MWE is a bit tricky. Hence, as Julien mentioned, an output of dput(df_beine_clan) would be helpful.
I tried to recreate an example, but this might not be applicable to the structure of your data. It might give you an example, however how to tackle the problem. I have created a column in the data table, that contains the label I think you want to add to your plot. Having a separate column gives you more flexibility inside ggplot.
library(tidyverse)
Group <- c("A", "A", "A", "B", "B", "B")
Value <- c(2,4,6,8,10,12)
Response <- c("Yes","No","Maybe","Yes","No","Maybe")
label <- Value
df <- data.frame(Group, Value, Response, label)
ggplot(df, aes(x = Group, y = Value, fill = Response)) + geom_bar(stat = "identity") +
geom_text(aes(label = label), position = position_stack(vjust = 0.5))
Changing the variable label to label <- sort(Value, decreasing = T) or label <- c("Blue", "Green", "Red", "Blue", "Green", "Red") gives you the two figures below.
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:
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
)
Is it possible to use the stroke argument introduced with ggplot2 2.0 to adjust the thickness of borders around bars? If not, is there a way to control bar-border thickness along the lines of point-border thickness? Stroke applies to borders around certain shapes -- see the second answer
A very modest MWE, showing fill only:
factor <- c("One", "Two", "Three", "Four")
value <- c(1, 2, 3, 4)
factor2 <- c("A", "B", "A", "B")
df <- data.frame(factor = factor(factor, levels = factor),
value = value, factor2 = factor2)
ggplot(df, aes(x = factor, y = value, color = factor2)) +
geom_bar(stat = "identity")
EDIT after COMMENT
OK, thanks to MLavoie's comment, it was so simple. Here is the code I have ended with, and, no, I am not actually using this plot other than to teach about ggplot and its capabilities.
ggplot(df, aes(x = factor, y = value, color = factor2)) +
scale_color_manual(values = c("darkgreen", "slateblue4")) +
geom_bar(stat = "identity", aes(fill = "transparent", size = ifelse(factor2 == "A", 2, 1))) +
guides(fill = FALSE) +
guides(size = FALSE) +
guides(color = FALSE)
well as I suggested by the OP, I will just recopy my comment as an answer.
you just need to set size in your geom_bar() expression:
geom_bar(stat = "identity", aes(fill = "transparent", size = ifelse(factor2 == "A", 2, 1)), size=2)