I would like to desaturate (or make gray) certain bars in a bar chart. I figured out how to make certain bars more transparent than others based on a column value using alpha=column_name in geom_bar. But I would like to make them gray not transparent. Is there a way to do it natively in ggplot?
Below is the code to make certain columns transparent based on column S. Is there a way to desaturate/make gray specific bars based on column value?
Edited code to include data.
data_t<-as.data.frame(Titanic)
join_table<- data_t %>% group_by(X=Class) %>% summarise(Y=sum(Freq)) %>%
mutate(S=ifelse(Y-mean(Y)>0,"a","b")) %>% select(X, S); join_table
data_t %>% group_by(X=Class, groups=Sex) %>% summarise(Y=sum(Freq)) %>%
inner_join(join_table, by=c("X")) %>%
ggplot(aes(x=X, y=Y)) + theme_minimal() +
geom_bar(aes(fill=groups, alpha=S), stat = "identity", position = "dodge")
Thanks in advance!
You can subset the data plotted each time and adjust the fill colour accordingly. The following should work:
library(tidyverse)
data_t <- as.data.frame(Titanic)
join_table <- data_t %>%
group_by(X = Class) %>%
summarise(Y = sum(Freq)) %>%
mutate(S = ifelse(Y - mean(Y) > 0, "a", "b")) %>%
select(X, S)
data_t %>%
group_by(X = Class, groups = Sex) %>%
summarise(Y = sum(Freq)) %>%
inner_join(join_table, by = c("X")) %>%
ggplot(aes(x = X, y = Y)) +
theme_minimal() +
geom_bar(data = . %>% filter( S == "b"),
aes(fill = groups), stat = "identity", position = "dodge") +
geom_bar(data = . %>% filter( S == "a"),
aes(group = groups),
fill = "grey80", stat = "identity", position = "dodge")
You can adjust fill = "grey80" to get the exact colour you'd like.
Related
I want to make several plots same space interval between bars regardless of sample numbers
As described below.
Not like this
My original script is
myData <- read.csv('L1L2_100percent.csv', header = T, sep =',')
ggplot(data = myData, aes(x = region, y = vaf, fill = type)) +
geom_bar(stat = "identity", width = 0.4) +
coord_flip()
I think it has to do with saving pictures with a specific height, but I think the height
has to be determined with sample numbers but I don't know the exact value.
You just need to adjust the height of the plot on saving proportional to the number of bars.
Here, plt1 has 5 instead of 10 bars thus it should be saved with a height that is only half than those of plt2:
library(tidyverse)
# create example data
myData <-
iris %>% transmute(
region = row_number() %% 20,
vaf = Sepal.Length,
type = Species
)
plt1 <-
myData %>%
filter(region < 5) %>%
ggplot(aes(x = region, y = vaf, fill = type)) +
geom_bar(stat = "identity") +
coord_flip()
plt2 <-
myData %>%
filter(region < 10) %>%
ggplot(aes(x = region, y = vaf, fill = type)) +
geom_bar(stat = "identity") +
coord_flip()
ggsave("plt1.png", plt1, height = plt1$data$region %>% unique() %>% length())
ggsave("plt2.png", plt2, height = plt2$data$region %>% unique() %>% length())
Plt1:
Plt2:
I'm making an area line chart. It's not stacked because they don't sit on top of each of the other lines.
The line part and the area part aren't lining up. I'd like to show two groups in one area line chart.
This is my code
economics_long %>%
filter(variable %in% c("unemploy", "pop")) %>%
ggplot(aes(date, value, group = variable,
fill = variable, color = variable)) +
geom_area(alpha = 0.4) +
geom_line(size = 1)
The red line doesn't match up with the top of the red area.
Maybe this is what you are looking for:
library(ggplot2)
#Code
economics_long %>%
filter(variable %in% c("unemploy", "pop")) %>%
ggplot(aes(date, value, group = variable,
fill = variable, color = variable)) +
geom_area(alpha = 0.4,size=1)
Output:
Or this:
#Code 2
economics_long %>%
filter(variable %in% c("unemploy", "pop")) %>%
ggplot(aes(date, value, group = variable,
fill = variable, color = variable)) +
geom_line(size=1)+
geom_area(alpha = 0.4,size=1,position='identity')
Output:
Or this stack style:
#Code 3
economics_long %>%
filter(variable %in% c("unemploy", "pop")) %>%
ggplot(aes(date, value, group = variable,
fill = variable, color = variable)) +
geom_line(size=1,position='stack')+
geom_area(alpha = 0.4,size=1,position='stack')
Output:
I am trying to use facet_wrap with stacked bar graphs, and I'd like to have labels on the bars showing the value of each part of the bar.
Using the diamonds dataset as an example:
My geom_text code works fine when there is only one graph, albeit cramped for the shorter bars:
diamonds %>%
ggplot(aes(x = cut, fill = clarity)) +
geom_bar() +
geom_text(data = . %>%
group_by(cut, clarity) %>%
tally() %>%
ungroup() %>%
group_by(cut) %>%
ungroup(),
aes(y = n, label = n),
position = position_stack(0.5),
show.legend = FALSE)
Labeled bar plot without faceting
However, when I add the faceting, all the labels display in all the individual facets:
diamonds %>%
ggplot(aes(x = cut, fill = clarity)) +
geom_bar() +
facet_wrap(~ color) +
geom_text(data = . %>%
group_by(cut, clarity) %>%
tally() %>%
ungroup() %>%
group_by(cut) %>%
ungroup(),
aes(y = n, label = n),
position = position_stack(0.5),
show.legend = FALSE)
Faceted bar plot with replicated labeling
How can I make it so that the labels only show up on the relevant bars?
Thanks!
I think you need to include color in the group_by + tally so that it can be assigned to the correct facet:
diamonds %>%
ggplot(aes(x = cut, fill = clarity)) +
geom_bar() +
facet_wrap(~ color,scale="free_y") +
geom_text(data = . %>%
count(cut, clarity,color),
aes(y = n, label = n),size=1,
position = position_stack(0.5),
show.legend = FALSE)
Personally, I find the ..count.. special variable to be easier to work with.
diamonds %>%
ggplot(aes(x = cut, fill = clarity)) +
geom_bar() +
facet_wrap(~ color,scale="free_y") +
stat_count(geom = "text",
aes(y =..count.., label = ..count..),
position=position_stack(0.5), size = 2)
I'm facing an issue with sorting bars when using facet_wrap (which is commonly reported here, here and others) after group variables and get top values.
When I run the code without factor conversion, bars are ordered:
iris %>%
gather(key = measurements, value = values, - Species) %>%
mutate(kk = factor(measurements, levels = unique(.$measurements)),
species_l = with(., paste(Species, .$measurements, sep = "_"))) %>%
ggplot(aes(x = reorder(species_l, values),
y = values,
fill = kk)) +
geom_bar(stat = "identity") +
facet_wrap(.~kk,
scales = "free")
But now I want to order decreasingly bars within facet_wrap and after top_n.
Heres is what I've tried so far:
library(tidyverse)
iris %>%
gather(key = measurements, value = values, - Species) %>%
within(.,
Species <- factor(Species,
levels=names(sort(table(Species),
decreasing=FALSE)))) %>%
ggplot(aes(x = Species,
y = values,
fill = measurements)) +
geom_bar(stat = "identity") +
facet_wrap(.~ measurements,
scales = "free")
and this:
iris %>%
gather(key = measurements, value = values, - Species) %>%
group_by(measurements, Species) %>%
top_n(5, wt = values) %>%
ggplot(aes(x = reorder(Species, Species,
function(x)-length(x)),
y = values,
fill = measurements)) +
geom_bar(stat = "identity") +
facet_wrap(.~measurements,
scales = "free")
and this:
iris %>%
gather(key = measurements, value = values, - Species) %>%
mutate(kk = factor(measurements, levels = unique(.$measurements)),
species_l = with(., paste(Species, .$measurements, sep = "_"))) %>%
group_by(measurements, Species) %>%
top_n(5, wt = values) %>%
ungroup() %>%
ggplot(aes(x = reorder(species_l, values),
y = values,
fill = kk)) +
geom_bar(stat = "identity") +
facet_wrap(.~kk,
scales = "free")
This is what I get:
As you can see Sepal.Width bars are not sorted.
Your first attempt was close -- you need to make sure you're reordering per facet, and not just reordering the factor based on the top 5 values of all measurements. Julia Silge explains thoroughly here
library(tidytext)
library(tidyverse)
library(magtrittr)
iris %>%
gather(key = measurements, value = values, - Species) %>%
mutate(kk = factor(measurements, levels = unique(.$measurements)),
#The '-values' below specifies to order in descending
Species = reorder_within(Species, -values, measurements)) %>%
ggplot(aes(x = Species, y = values, fill = kk)) +
geom_bar(stat = "identity") +
facet_wrap(.~kk, scales = "free") +
scale_x_reordered()`
I tried the following code but instead of showing the label in middle, I want to point it to leftmost (you can see my picture under). Thanks for the help!
library(tidyverse)
library(ggrepel)
mtcars %>%
group_by(am, cyl) %>%
slice(1) %>%
ggplot(aes(x = am, y = mpg, group = cyl, fill = cyl, label = mpg)) +
geom_bar(position = "dodge", stat = "identity") +
geom_label_repel(data = mtcars %>% filter(am == 0,
cyl == 4) %>%
slice(1),
nudge_x = 0.2,
nudge_y = 0.3,
aes(fill = NULL))
Created on 2019-01-22 by the reprex package (v0.2.1)
This solution will work generally, for any combination of labels.
First, it seems as if the am variable is a binary factor, so I code it as a factor so the x axis is a little cleaner. In your case, you are looking for position_dodge(width = 1) for your labels, which automatically lines the labels up on top of the corresponding bars. The way I thought was best for subsetting to only the one label you want us ti define a column mpg_lab which is NA for all the labels you don't want. If you change the conditions in the last mutate row you can isolate different labels, or delete that row altogether for all the labels.
df <- mtcars %>%
mutate(am = factor(am)) %>%
group_by(am, cyl) %>%
slice(1) %>%
mutate(mpg_lab = ifelse(am == 0 & cyl == 4, mpg, NA))
df %>%
ggplot(aes(x = am, y = mpg, group = cyl, fill = cyl)) +
geom_bar(position = "dodge", stat = "identity") +
geom_label_repel(data = df,
aes(label = mpg_lab, fill = NULL), position = position_dodge(width = 1), point.padding = NA, ylim = max(df$mpg_lab, na.rm = T) * 1.02)
A couple of optional things I added was turning off point.padding in geom_label_repel to keep the labels from randomly moving around side-to-side. I also bumped the label up so you can see the arrow by using the ylim argument in there. You can play around with those options if you want something different.
On way is to use geom_text instead. You don't get the white background around the label, but you can position it exactly:
mtcars %>%
group_by(am, cyl) %>%
slice(1) %>%
ggplot(aes(x = am, y = mpg, group = cyl, fill = cyl, label = mpg)) +
geom_bar(position = "dodge", stat = "identity") +
geom_text(data = mtcars %>% filter(am == 0,cyl == 4) %>% slice(1),
nudge_x = -0.3,
nudge_y = 0.7,
aes(fill = NULL))
Edit:
As pointed out, geom_label will make the white background, which is a much nicer option :P