Related
I'd like to be able to change the colour palette in ggplot2 boxplots, according to another variable data_origin.
This makes my boxplots, complete with legend:
library(hrbrthemes)
library(ggplot2)
library(reshape2)
library(tidyverse)
data_origin <- "airborne"
mytitle <- "something more than this"
legend_title <- "some words"
melted <- reshape2::melt(iris)
bp1 <- ggplot(melted, aes(x = variable, y = value, fill = Species)) +
geom_boxplot() +
theme_ipsum() +
scale_fill_brewer(palette = "Greens") +
theme(
legend.position = "bottom",
plot.title = element_text(size = 10)) +
theme(axis.text.x = element_blank()) +
ggtitle(mytitle) +
xlab("") +
ylab("") +
facet_wrap(~variable, scale = "free")
bp1
This however drops the legend completely and ignores the if else:
bp1 <- ggplot(melted, aes(x = variable, y = value, fill = Species)) +
geom_boxplot() +
theme_ipsum() +
scale_fill_brewer(legend_title, if (data_origin == "airborne" ) {palette = "Blues"} else {palette = "Greens"}) +
theme(
legend.position = "bottom",
# legend.title = legend_title,
plot.title = element_text(size = 10)) +
theme(axis.text.x = element_blank()) +
ggtitle(mytitle) +
xlab("") +
ylab("") +
facet_wrap(~variable, scale = "free")
bp1
Besides what #stefan suggested, there are two ways in which you can do this (that I know of). The first is using ifelse() (I moved the relevant part to the end):
data_origin <- "airborne"
bp1 <- ggplot(melted, aes(x = variable, y = value, fill = Species)) +
geom_boxplot() +
theme_ipsum() +
theme(
legend.position = "bottom",
# legend.title = legend_title,
plot.title = element_text(size = 10)) +
theme(axis.text.x = element_blank()) +
ggtitle(mytitle) +
xlab("") +
ylab("") +
facet_wrap(~variable, scale = "free") +
scale_fill_brewer(legend_title, palette = ifelse(
data_origin == "airborne",
"Blues",
"Greens"
))
bp1
The other one is to build the plot up in two steps:
data_origin <- "not airborne"
bp1 <- ggplot(melted, aes(x = variable, y = value, fill = Species)) +
geom_boxplot() +
theme_ipsum() +
theme(
legend.position = "bottom",
# legend.title = legend_title,
plot.title = element_text(size = 10)) +
theme(axis.text.x = element_blank()) +
ggtitle(mytitle) +
xlab("") +
ylab("") +
facet_wrap(~variable, scale = "free")
if (data_origin == "airborne") {
bp2 <- bp1 +
scale_fill_brewer(legend_title, palette = "Blues")
} else {
bp2 <- bp1 +
scale_fill_brewer(legend_title, palette = "Greens")
}
bp2
Created on 2021-08-01 by the reprex package (v2.0.0)
I've produced a bar graph, however I want the data to be switched.
I want the blue area (the live cells) on the bottom and the dead cells on the top.
I tried reorder, reordering it by making it a factor but it all didn't work.
Who can help me?
Code I have now:
b_stack1<-ggplot(Stack1, aes(x=Condition, y=N, fill=Type)) +
geom_bar(aes(fill = Type), stat="identity", position="stack", color="black") +
scale_fill_manual(values=c("lightblue","grey")) +
theme_bw() + theme(legend.position="right", axis.title.x = element_blank())
Graph I have now:
library(forcats)
b_stack1<-ggplot(Stack1, aes(x=Condition, y=N, fill=fct_shift(Type))) +
geom_bar(aes(fill = Type), stat="identity", position="stack", color="black") +
scale_fill_manual(values=c("lightblue","grey")) +
theme_bw() + theme(legend.position="right", axis.title.x = element_blank())
Have you tried position_stack(reverse = TRUE)?
b_stack1<-ggplot(Stack1, aes(x=Condition, y=N, fill=Type)) +
geom_bar(aes(fill = Type), stat="identity", position = position_stack(reverse = TRUE)), color="black") +
scale_fill_manual(values=c("lightblue","grey")) +
theme_bw() + theme(legend.position="right", axis.title.x = element_blank())
`install.packages("forcats")
b_stack1<-ggplot(Stack1, aes(x=Condition, y=N, fill = forcats::fct_rev(Type))) +
geom_bar(stat="identity", position="stack", color="black") +
scale_fill_manual(values=c("lightblue","grey"))`
Forcats did the trick
I have a data frame df
Group Time_Period mean uci lci
1 A Before 4.712195 5.054539 4.369852
2 A After 5.881463 6.241784 5.521142
3 B Before 5.349754 5.872940 4.826567
4 B After 6.653595 7.246231 6.060959
I want to plot this to illustrate that there is no difference in the mean increase between groups. I tried the following :
ggplot(df, aes(x=Time_Period, y=mean, fill=Group)) +
geom_bar(stat="identity", position=position_dodge(width = 1), color="black") +
geom_point(position = position_dodge(width = 1))+
geom_line(aes(group=Group, color=Group), color=c("cyan4","firebrick","cyan4","firebrick"), size =1, position = position_dodge(width = 1)) +
geom_errorbar(aes(ymin=lci, ymax=uci), position=position_dodge(width = 1)) +
theme_bw() +
scale_y_continuous(limits=c(-0.2,8), breaks= seq(0,300,1), minor_breaks=seq(0,300,0.5)) +
theme(panel.grid.minor = element_line(colour="lightgrey", size=0.5)) +
theme(panel.grid.major = element_line(colour="grey", size=0.5)) +
labs(y="Sales", x="Time Period", fill="Category") +
theme(axis.text.x = element_text(face="bold", size=12)) +
theme(axis.text.y = element_text(face="bold", size=12)) +
theme(axis.title.x = element_text(face="bold", size=16)) +
theme(axis.title.y = element_text(face="bold", size=16)) +
theme(legend.text= element_text(face="bold", size=12)) +
theme(legend.title= element_text(face="bold", size=16))
which plots:
However my manager is concerned it is difficult to differentiate the two lines due to the overlap, so he told me to rearrange the columns so that x is Group and fill is Time Period.
I tried the following:
ggplot(df, aes(x=Group, y=mean, fill=Time_Period)) +
geom_bar(stat="identity", position=position_dodge(width = 1), color="black") +
geom_point(position = position_dodge(width = 1))+
geom_line(aes(group=Group), color="black", size =1, position = position_dodge(width = 1)) +
geom_errorbar(aes(ymin=lci, ymax=uci), position=position_dodge(width = 1)) +
theme_bw() +
scale_y_continuous(limits=c(-0.2,8), breaks= seq(0,300,1), minor_breaks=seq(0,300,0.5)) +
theme(panel.grid.minor = element_line(colour="lightgrey", size=0.5)) +
theme(panel.grid.major = element_line(colour="grey", size=0.5)) +
labs(y="Sales", x="Group", fill="Time Period") +
theme(axis.text.x = element_text(face="bold", size=12)) +
theme(axis.text.y = element_text(face="bold", size=12)) +
theme(axis.title.x = element_text(face="bold", size=16)) +
theme(axis.title.y = element_text(face="bold", size=16)) +
theme(legend.text= element_text(face="bold", size=12)) +
theme(legend.title= element_text(face="bold", size=16))
But I can't work out how to get the lines to plot correctly between the two bars instead of just vertically in the centre, even if I adjust the "width" argument for position_dodge:
Please could anyone advise me on how to fix the plot?
You're looking for position_dodge2(). There's a little about it on the ggplot2 dodge reference, and a little more in the actual code on Github. The relevant section below, with some emphasis added:
Dodging preserves the vertical position of an geom while adjusting the
horizontal position. position_dodge2 is a special case of position_dodge
for arranging box plots, which can have variable widths. position_dodge2
also works with bars and rectangles. But unlike position_dodge,
position_dodge2 works without a grouping variable in a layer.
So here's the code, with some of the theming removed.
library(tidyverse)
txt = "
Group Time_Period mean uci lci
1 A Before 4.712195 5.054539 4.369852
2 A After 5.881463 6.241784 5.521142
3 B Before 5.349754 5.872940 4.826567
4 B After 6.653595 7.246231 6.060959"
df <- read.table(text = txt, header = TRUE) %>%
mutate(Group = fct_relevel(Group, "A", "B")) %>%
mutate(Time_Period = fct_relevel(Time_Period, "Before", "After"))
ggplot(df, aes(x=Group, y=mean, fill=Time_Period)) +
geom_bar(stat="identity", position=position_dodge(width = 1), color="black") +
geom_point(position = position_dodge(width = 1))+
geom_line(aes(group=Group), color="black", size =1,
position = position_dodge2(width = 1)) +
geom_errorbar(aes(ymin=lci, ymax=uci), position=position_dodge(width = 1)) +
theme_bw() +
scale_y_continuous(limits=c(-0.2,8), breaks= seq(0,300,1), minor_breaks=seq(0,300,0.5)) +
labs(y="Sales", x="Group", fill="Time Period")
Created on 2019-11-21 by the reprex package (v0.3.0)
library(ggplot2)
df <- data.frame(Treatment=c("A", "B","A","B"), Value=c(3,4, 20,2), SE=c(1,1,5,1), Type=c("c1","c1","c2","c2"))
p1 <- ggplot(df, aes(Treatment, Value,fill=Treatment)) +
geom_bar(stat="identity", col="Black") +
geom_errorbar(aes(ymax = Value + SE, ymin=Value), col="black") +
facet_wrap(~Type, scale="free_y") +
theme(panel.background = element_blank(),
panel.border = element_rect(colour = "black", fill=NA),
strip.background = element_blank())
p1
I want to remove the white space between bar and x-axis:
p1 + scale_y_continuous(expand = c(0,0))
This also removes white space between the geom and the maximum of the y-axis. One way to prevent this is to control the limits of the y-axis
p1 + scale_y_continuous(expand = c(0,0), limits=c(0,26))
But now panel c1 has lots of white space, as limits apparently overrides scale="free", which is especially irrating when the panels are arranged in columns.
So, i need to have the expand-argument and scale="free" active at the same time. Is it possible?
You may want to use a geom_blank():
Please be considerate and try not to confound the user! This type of transformation can be dangerous!
library(ggplot2)
df <- data.frame(Treatment=c("A", "B","A","B"), Value=c(3,4, 20,2), SE=c(1,1,5,1), Type=c("c1","c1","c2","c2"))
ggplot(df, aes(Treatment, Value,fill=Treatment)) +
geom_bar(stat="identity", col="Black") +
geom_errorbar(aes(ymax = Value + SE, ymin=Value), col="black") +
geom_blank(aes(y=Value + SE + 1)) +
facet_wrap(~Type, scale="free_y") +
theme(panel.background = element_blank(),
panel.border = element_rect(colour = "black", fill=NA),
strip.background = element_blank()) +
scale_y_continuous(expand = c(0,0))
Or:
ggplot(df, aes(Treatment, Value,fill=Treatment)) +
geom_bar(stat="identity", col="Black") +
geom_errorbar(aes(ymax = Value + SE, ymin=Value), col="black") +
geom_blank(aes(y=Value + 2 * SE)) +
facet_wrap(~Type, scale="free_y") +
theme(panel.background = element_blank(),
panel.border = element_rect(colour = "black", fill=NA),
strip.background = element_blank()) +
scale_y_continuous(expand = c(0,0))
Created on 2018-05-17 by the reprex package (v0.2.0).
I'm sure this is simple but I can't figure it out.
I have the following chart:
library(data.table)
library(magrittr)
library(ggplot2)
cambodia <-
data.table(Period = c("Funan", "Chenla/Zhenla","Khmer Empire","Dark Ages of Cambodia"),
StartDate = c(-500,550,802,1431),
EndDate = c(550,802,1431,1863),
Color = c("lightblue","lightgreen","lightyellow","pink")) %>%
extract(order(-StartDate)) %>%
extract(, Period := factor(Period,levels = Period))
ggplot() +
geom_segment(data=cambodia, aes(x=StartDate, xend=EndDate, y=Period, yend=Period, color=Color),
linetype=1, size=2) +
scale_colour_brewer(palette = "Pastel1")+
xlab("Date")+
ylab("Ruler")+
theme_bw() +
theme(panel.grid.minor = element_blank(), panel.grid.major = element_blank()) +
theme(aspect.ratio = .2) +
theme(legend.position="none")
But I would like the labels to be off the axis and on the page. Either to the left or on top of the middle of the line. E.g.
Most of the examples of geom_text give me gobbledeegook. I can't seem to apply them to the factor data I have here. Do you know how to do this?
Thank you
Having the labels on the end of the segments might distort the visual mapping of segment length and location to year-range. You could put the labels in the middle of the segments instead.
library(data.table)
library(magrittr)
library(ggplot2)
library(stringr)
cambodia <-
data.table(Period = c("Funan", "Chenla/Zhenla","Khmer Empire","Dark Ages of Cambodia"),
StartDate = c(-500,550,802,1431),
EndDate = c(550,802,1431,1863),
Color = c("lightblue","lightgreen","lightyellow","pink")) %>%
extract(order(-StartDate)) %>%
extract(, Period := factor(Period,levels = Period))
ggplot(cambodia, aes(x=StartDate, xend=EndDate, y=Period, colour=Period)) +
geom_segment(aes(xend=EndDate, yend=Period), linetype=1, size=2) +
geom_label(aes(label=str_wrap(Period,12), x=(StartDate + EndDate)/2), size=3) +
scale_colour_brewer(palette = "Set1") +
xlab("Date")+ ylab("Ruler")+
theme_bw() +
theme(panel.grid.minor = element_blank(), panel.grid.major = element_blank(),
aspect.ratio = .2,
legend.position="none",
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
Or what about going minimal:
ggplot(cambodia, aes(x=StartDate, y=1)) +
geom_rect(aes(xmin=StartDate, xmax=EndDate, ymin=0.97, ymax=1.03, fill=Period),
show.legend=FALSE, colour="white", size=0.5) +
geom_label(aes(label=str_wrap(Period,12), x=(StartDate + EndDate)/2), size=3.5) +
geom_text(aes(label=StartDate, y=0.96), size=3.5) +
geom_text(aes(label=ifelse(EndDate==max(EndDate), EndDate,""), x=EndDate, y=0.96), size=3.5) +
scale_colour_brewer(palette = "Set1") +
scale_y_continuous(limits=c(0.95,1.05)) +
theme_void()
ggplot() +
geom_segment(data=cambodia, aes(x=StartDate, xend=EndDate, y=Period, yend=Period, color=Color),
linetype=1, size=2) +
geom_label(data=cambodia, aes(x=StartDate, y=Period, label = Period),
nudge_x = c(-300, -200, -200, -100)) +
scale_colour_brewer(palette = "Pastel1")+
xlab("Date")+
ylab("")+
theme_bw() +
theme(legend.position="none") +
theme(aspect.ratio = .2) +
theme(panel.grid.minor = element_blank(), panel.grid.major = element_blank(),
axis.line.y = element_blank(), axis.text.y = element_blank(),
axis.ticks.y = element_blank())
You need to use element_blank() to remove the y axis elements and then use nudge_x argument in geom_label to offset the labels appropriately.