pet_bar <- ggplot(pet_adopt, aes(x=Size, group = Status)) +
geom_bar(width= 0.65, aes(fill= Status)) +
geom_text(stat="count", position = position_stack(vjust= 0.5), aes(fill=Size,label = ..count..)) +
theme(legend.position = c(0.93, 0.88), axis.title = element_blank(), panel.background = element_blank(), axis.line.x = element_line(colour = "gray"), axis.ticks = element_blank(), panel.grid.minor.y = element_blank()) +
facet_grid(~gender) +
scale_fill_manual(values = c("gray60", "gray90")) +
ggtitle("Adoption Status of Dogs during the Summer of 2020")
pet_bar
Some fake data, so I can reproduce your plotting code:
fake_pet_adopt = crossing(gender = c("Female", "Male"),
Status = c("Adopted", "Not Adopted"),
Size = c("Large", "Medium", "Small")) %>%
mutate(number = 32:21) %>%
uncount(number)
Edit: I misread the original question before, and have updated here to have the text over the bars represent "% adopted" not total #. There are a few calculations, so I find it simpler to do those before ggplot using dplyr functions:
fake_pet_adopt_counts <- fake_pet_adopt %>%
count(gender, Size, Status)
adopt_shares <- fake_pet_adopt_counts %>%
group_by(gender, Size) %>%
mutate(total = sum(n),
share = n / sum(n)) %>%
filter(Status == "Adopted")
Then we can feed those in, where one text layer uses the adopt_shares table to get the % labels and locations:
ggplot(fake_pet_adopt_counts,
aes(x=Size, y = n, label = n, group = Status)) +
geom_col(width= 0.65, aes(fill= Status)) +
geom_text(position = position_stack(vjust= 0.5)) +
geom_text(data = adopt_shares, vjust = -0.2,
aes(y = total, label = scales::percent(share, accuracy = 0.1))) +
theme(legend.position = c(0.93, 0.88), axis.title = element_blank(), panel.background = element_blank(), axis.line.x = element_line(colour = "gray"), axis.ticks = element_blank(), panel.grid.minor.y = element_blank()) +
facet_grid(~gender) +
scale_fill_manual(values = c("gray60", "gray90")) +
ggtitle("Adoption Status of Dogs during the Summer of 2020")
Related
This is my code I currently have to compare responses by year, but I want to be able to add the variable of race to be displayed in the data. Such as stacked data with a legend with different colors to represent race.
data1820$Q8_4 = car::recode(data1820$Q8_4, "1='Yes'; 2 = 'No'; 3 = 'NR'")
data1820$Q8_4 <-
factor(data1820$Q8_4, levels = c("Yes", "No", "NR"))
#Do you currently have any kind of health coverage
df <-
data1820 %>% group_by(year) %>% count(Q8_4) %>% na.omit() %>%
mutate(Percent = n / sum(n) * 100)
g <- ggplot(df, aes(x = Q8_4, y = Percent, fill = year)) +
geom_bar(stat = 'identity') +
facet_grid(cols = vars(year)) +
theme(
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
strip.background = element_blank(),
panel.spacing = unit(4, "lines"),
text = element_text(family = "Helvetica",
size = 10),
axis.ticks.x = element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
plot.title = element_text(hjust = 0.5, vjust = 2),
legend.title = element_blank(),
legend.position = "none",
plot.margin = margin(10, 10, 10, 10)
) +
labs(title = "Do you currently have any kind of health coverage",
y = "Percentage",
fill = "year") +
scale_fill_manual(values = colors, na.value = "grey") +
scale_y_continuous(labels = scales::percent_format(scale = 1)) +
scale_linetype_manual(guide = guide_legend(reverse = TRUE))
How can I implement histogram with such complex x-axis?
First x-axis row is the week start, second - week end.
Data for tests in csv: https://gofile.io/d/FrhLZh.
What I managed to
hist_data %>%
ggplot(aes(x = week, y = count)) +
geom_col(fill = "#5B879E", width = 0.9, size = 0.7) +
labs(title = "", x = "", y = "") +
theme_bw() + theme_minimal() + theme(legend.position="none")+
theme(
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor.y = element_blank(),
axis.text.y = element_blank(),
axis.text.x = element_text(vjust = 0.5, size = 8, family = "Inter", colour = "#ffffff"),
axis.line.x = element_blank(),
axis.title.x = element_blank(),
plot.background = element_rect(fill = "#3A464F"),
plot.margin=unit(c(0,0.25,0.5,0), "cm"))+
scale_x_discrete(expand=c(0,0), labels = format(as.Date(hist_data$week_start), "%d-%m"), position = "bottom") +
scale_y_continuous()
Thanks to teunbrand and his ggh4x package, solution:
hist_data %>%
ggplot(aes(x = week, y = count)) +
geom_col(fill = "#5B879E", width = 0.8, size = 0.7)+
labs(title = "", x = "", y = "") +
theme_bw() + theme_minimal() + theme(legend.position="none")+
theme(
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor.y = element_blank(),
axis.text.y = element_blank(),
axis.text.x = element_text(vjust = 0.5, size = 8, lineheight = 0.8, family = "Inter", colour = "#ffffff"),
axis.line.x = element_blank(),
axis.title.x = element_blank(),
ggh4x.axis.nestline.x = element_line(size = 0.5, colour = "#5B879E", lineend = "square"),
plot.background = element_rect(fill = "#3A464F"),
plot.margin=unit(c(1,0.5,1,0.5), "cm"))+
scale_x_discrete(expand=c(0,0),
labels = paste0(format(as.Date(sort(hist_data$week_start)), "%d.%m"),
"\n", "nonsense", "\n",
format(as.Date(sort(hist_data$week_end)), "%d.%m")), position = "bottom") +
scale_y_continuous() +
guides(x = guide_axis_nested(delim = "nonsense"))
You can add multiple layers of geom_text and geom_segment. Adjust the relative y positions of these layers using a scaling factor.
plotscale <- max(hist_data$count)/50
library(ggplot2)
ggplot(data = hist_data,
aes(x = week_start + floor(week_end-week_start)/2, y = count)) +
geom_col(fill = "#5B879E", width = 4) +
geom_text(aes(y = -6 * plotscale ,
label = format(week_start, "%m-%d")),
color = "#ffffff")+
geom_segment(aes(x = week_start, xend = week_end,
y = -10 * plotscale, yend = -10 * plotscale),
color = "#5B879E", size = 1.5)+
geom_text(aes(y = -14 * plotscale,
label = format(week_end, "%m-%d")),
color = "#ffffff")+
theme_minimal() +
theme(
panel.grid = element_blank(),
axis.text = element_blank(),
axis.title = element_blank(),
plot.background = element_rect(fill = "#3A464F"))+
scale_x_date(expand=c(0,0), date_breaks = "1 week",
labels = NULL)
Consider using ggh4x package for more complex nested x axes.
Raw Data
hist_data <- read.table(text='"","week","count","week_start","week_end"
"1","1",21.5823972708382,2021-01-04,2021-01-10
"2","2",36.122556304552,2021-01-11,2021-01-17
"3","3",34.2809483156697,2021-01-18,2021-01-24
"4","4",25.8546925450454,2021-01-25,2021-01-31
"5","5",29.0309819292706,2021-02-01,2021-02-07
"6","6",33.1503608888827,2021-02-08,2021-02-14
"7","7",27.0490347440184,2021-02-15,2021-02-21
"8","8",30.3031289757874,2021-02-22,2021-02-28
"9","50",32.2876434072602,2020-12-07,2020-12-13
"10","51",33.1939593686481,2020-12-14,2020-12-20
"11","52",26.6853246329896,2020-12-21,2020-12-27
"12","53",23.0715199391151,2020-12-28,2021-01-03', header = TRUE, sep = ",")
hist_data$week_start <- as.Date(hist_data$week_start)
hist_data$week_end <- as.Date(hist_data$week_end)
Using the code below, I have created my plot of interest. The only issue is the break between the brown line the rest of the four lines (Year=205). How can I solve this by joining the brown line to the other four lines?
Thanks,
Nader
UN_2010_plot <- ggplot()+
geom_line(aes(x =Year, y =Population , group=Variant, colour = Variant), data = UN_2010)+
ggrepel::geom_text_repel(aes(x =Year+10, y = Population, colour = Variant, label = Variant, fontface = 'bold'), data = UN_2010 %>%
filter(Year == max(Year)),
segment.color = 'transparent',
direction = "y",
size = 3,
box.padding = 0,
force = 0
) +
theme_bw() +
theme(panel.border = element_blank(), panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), axis.line = element_line(colour = "black"),
strip.background = element_rect(
color="white", fill="white", size=1.5, linetype="solid"
))+
theme(legend.position = "none") +
scale_x_continuous(breaks=seq(1950,2100,10))+
scale_y_continuous(breaks=seq(10000,150000,10000))+
coord_cartesian(ylim = c(10000, 150000))+
labs(
x = NULL,
y = "Population (thousands)",
caption = (NULL),
face = "bold"
) +
ggtitle("The 2010 Revision") +
theme(plot.title = element_text(hjust = 0.5))+
theme(axis.text.x = element_text(angle = -45, vjust = 0.5, hjust=0))
UN_2010_plot
As stefan already mentioned. Here is the psuedo code that fixed your data which would connect the ending lines with starting line.
additional_data <- tibble(Year = rep(2010, 4),
Population = rep(UN_2010$Population[Year == "2010"], 4),
Variant <- c("Low", "Medium", "Constant", "High"))
UN_2010_new <- bind_rows(UN_2010, additional_data) %>% arrange(Year, Variant)
I've come across several threads pointing out how to annotate bar charts, but I've tried a number of iterations of this code and can't seem to get the text left justified, starting at 0% on the x axis. I've tried to change hjust to "left", 0.95, and progressively larger numbers - none of them have the text tethered to the x origin.
dummy_data <- tibble(Proportion = c(0.87, 1),
`Person of Interest` = c("Person B", "Person A"))
dummy_data %>%
ggplot(aes(x = Proportion, y = `Person of Interest`,
fill = `Person of Interest`,
label = paste0(`Person of Interest`, "~", scales::percent(Proportion))))+
geom_col(width = 0.5) +
geom_text(position = position_dodge(width = .9), # move to center of bars
vjust = 0, # nudge above top of bar
hjust = "top",
size = 4.5,
colour = "white",
fontface = "bold") +
scale_x_continuous(labels = scales::percent,
limits = c(0, 1.01),
expand = c(0, 0)) +
ggthemes::theme_economist(horizontal = F) +
scale_fill_manual(values = alpha(c("black", "#002D62"), .5)) +
ggtitle("Lack of Skill") +
theme(title = element_text("Lack of Skill"),
plot.title = element_text(hjust = 0.5, face = "italic"),
axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.x = element_blank(),
axis.text.x = element_text(hjust = 0.25),
legend.position="none",
aspect.ratio = 1/3)
I've often found text data with ggplot maddening - a huge thanks to anyone willing to take a look.
Try this approach that is close to what you want. Your themes can be producing the issues with placing the labels:
#Code
dummy_data %>%
ggplot(aes(x=`Person of Interest`,
y=Proportion,
fill=`Person of Interest`,
label = paste0(`Person of Interest`, "~", scales::percent(Proportion))))+
geom_bar(stat = 'identity')+
geom_text(aes(y=0.13),
size = 4.5,
colour = "white",
fontface = "bold")+coord_flip()+
scale_y_continuous(labels = scales::percent,
limits = c(0, 1.01),
expand = c(0, 0)) +
ggthemes::theme_economist(horizontal = F) +
scale_fill_manual(values = alpha(c("black", "#002D62"), .5)) +
ggtitle("Lack of Skill") +
theme(title = element_text("Lack of Skill"),
plot.title = element_text(hjust = 0.5, face = "italic"),
axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.x = element_blank(),
axis.text.x = element_text(hjust = 0.25),
legend.position="none",
aspect.ratio = 1/3)
Output:
I have plotted a donut chart with the code below:
library(tidyverse)
library(ggthemes)
df <- data.frame(flavor = c("Chocolate", "Strawberry", "Pistachio"),
per_sold = c(.20, .30, .50))
df %>%
ggplot(aes(x = 2, y = per_sold, fill = flavor)) +
geom_bar(stat = "identity") +
xlim(0.5, 2.5) +
coord_polar(start = 0, theta = "y") +
xlab("") +
ylab("") +
theme(axis.ticks = element_blank(),
axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank(),
panel.border = element_blank(),
legend.title = element_text(size = rel(2)),
legend.text=element_text(size=rel(1.5))) +
geom_text(aes(label = per_sold), size = 6)
Out:
As you can see, the position of labels are not correct, also I want it show the format of % instead of float number with digit.
How could I modify the code to achive this? Thanks.
All you need is position_stack(vjust = 0.5) and scales::percent:
library(scales)
df %>%
ggplot(aes(x = 2, y = per_sold, fill = flavor)) +
geom_bar(stat = "identity") +
xlim(0.5, 2.5) +
coord_polar(start = 0, theta = "y") +
xlab("") +
ylab("") +
theme(axis.ticks = element_blank(),
axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank(),
panel.border = element_blank(),
legend.title = element_text(size = rel(2)),
legend.text=element_text(size=rel(1.5))) +
geom_text(aes(label = scales::percent(per_sold)),
size = 6, position = position_stack(vjust = 0.5))