R ggplot2: how to automatically adjust the grey area behind the barplot - r

I want to adjust make the width of the gray area and the bar plot smaller.
Now the grey area on the left and right to the plot is too much as you can see in my screenshot. Looking for a solution that also captures the scenario that I have 3 or more bars in the chart.
ggplot(data=MyDataFrame, aes(x='Text', y=MetricColumn, fill=LegendTag))+
scale_fill_brewer(palette="Set3")+
geom_bar(stat="identity", width=0.2)+
geom_text(aes(label=paste0(MetricColumn,"%")), position = position_stack(vjust = .5), size = 3.5, color = "black")+
labs(title="Text of the title")+
theme(plot.title = element_text(hjust = 0.5, face="bold"))+
theme(legend.position="left")

What James Martherus says is definitly part of the solution. But since a plot always fills out the whole plotting window it will look weird. So youc an either set the plot margins:
ggplot(data=diamonds, aes(x= "Text", y= ..count../sum(..count..), fill = cut,
label = scales::percent(..count../sum(..count..)))) +
scale_fill_brewer(palette="Set3")+
geom_bar(stat="count", show.legend = F) +
geom_text(stat = 'count', position = position_stack(vjust = .5), size = 3, color = "black") +
labs(x = NULL) +
scale_y_continuous(labels = scales::percent, name = "Percent") +
theme(plot.margin = unit(c(0.5,7, 0.5, 7), "cm"))
Or you just save it the way you want it to be:
p <- ggplot(data=diamonds, aes(x= "Text", y= ..count../sum(..count..), fill = cut,
label = scales::percent(..count../sum(..count..)))) +
scale_fill_brewer(palette="Set3")+
geom_bar(stat="count", show.legend = F) +
geom_text(stat = 'count', position = position_stack(vjust = .5), size = 6, color = "black") +
labs(x = NULL) +
scale_y_continuous(labels = scales::percent, name = "Percent") +
theme(axis.title.y = element_text(size = 20),
axis.text = element_text(size = 15))
ggsave("D:/R/plot.png", width = 5, height = 15, dpi = 200)
This way you get it without the margins.

Remove the width=.2 from geom_bar as you're telling R to make your bar take up only 20% of the plot. geom_bar sets the default width at 90% of the plot (see the documentation).
ggplot(data=MyDataFrame, aes(x='Text', y=MetricColumn, fill=LegendTag))+
scale_fill_brewer(palette="Set3")+
geom_bar(stat="identity")+
geom_text(aes(label=paste0(MetricColumn,"%")), position = position_stack(vjust = .5), size = 3.5, color = "black")+
labs(title="Text of the title")+
theme(plot.title = element_text(hjust = 0.5, face="bold"))+
theme(legend.position="left")

Related

facet grid to split the ggplot bar plot by group

I want to draw a bar plot using ggplot, with reorder the variables based on each group and split the gg bar plot by the groups. Here a samples example.
M <- data.frame(group = c(rep("A", 3), rep("B",4), rep("C", 2)), values = runif(9,-3,4), names = paste0("G", seq(1,9)))
ggplot(M) +
theme_minimal() +
aes(x = reorder(names,values), y = values, fill = factor(sign(values))) +
geom_bar(stat="identity", width = 0.5, show.legend = T, alpha = 0.75, position=position_dodge()) +
scale_fill_manual(values=c('mediumorchid4', 'goldenrod')) +
ggtitle("") +
theme(axis.text.y = element_text(size = "12", face = "bold"),
plot.title = element_text(face = "bold" , size = 10)) +
xlab("Names") +
ylab("Values") +
geom_hline(yintercept = 0, size = 1, color = "black") +
coord_flip()
For this example, I want to reorder the samples based on each group, then split horizontally by the groups, and the bar colors adjust by the sign of the values to different colors. Thank you.
It sounds like you are looking for something like this:
ggplot(M) +
theme_minimal() +
aes(x = reorder(names, values), y = values, fill = factor(sign(values))) +
geom_bar(stat="identity", width = 0.5, show.legend = TRUE, alpha = 0.75,
position=position_dodge()) +
scale_fill_manual(values=c('mediumorchid4', 'goldenrod')) +
ggtitle("") +
theme(axis.text.y = element_text(size = "12", face = "bold"),
plot.title = element_text(face = "bold" , size = 10)) +
xlab("Names") +
ylab("Values") +
geom_hline(yintercept = 0, size = 1, color = "black") +
coord_flip() +
facet_grid(group~., space = "free_y", scales = "free_y", drop = TRUE)

Overlapping text on top of geom_bar in ggplot2

I have made a barplot similar to the one below using ggplot2.
I cannot get the percentages on top of the bars to be centered and not overlapping of other bars and numbers. Sample code is below.
library(tidyverse)
cat1=c("cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1",
"cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2",
"cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3",
"cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4")
cat2=c("c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12",
"c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12",
"c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12",
"c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12")
count1=round(rnorm(48,10))
fakeperc=rnorm(48,9)
df1=cbind(count1,fakeperc)
df2=cbind(cat1,cat2)
finaldf=as.data.frame(cbind(df1,df2))
finaldf$cat1=as.factor(finaldf$cat1)
finaldf$fakeperc=as.numeric(finaldf$fakeperc)
#finaldf$cat1=factor(finaldf$cat1,levels = c("cat1","cat2","cat3","cat4"))
finaldf$cat2 = factor(finaldf$cat2,
levels = c("c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12"))
a=ggplot(data=finaldf,aes(x=cat1, y=count1,
fill=cat2,group=cat2)) +
geom_bar(stat='identity',color='black',width=.65,position=position_dodge(width=.9))+
scale_y_discrete(limits=0:50,breaks=c(0,10,20,30,40,50))+
scale_fill_brewer(palette="Set3") +
theme_classic() +
geom_text(data = finaldf,
aes(x=cat1,y=count1,group=cat2,
label=format(paste(round(fakeperc),"%",sep = ""))),inherit.aes = F,
color='black',position=position_dodge(.9),vjust=-.5,size=3)
a
When trying to add either nudge_y or nudge_x to the geom_text call, nothing happens. I suspect this is because there is already a position_dodge call. I am open any and all solutions to make these percentages non-overlapping and legible.
What do you think of this?
# I think you meant count1 to be numeric
finaldf$count1 <- as.numeric(finaldf$count1)
ggplot(data = finaldf,
aes(x = cat1,
y = count1,
fill = cat2,
group = cat2)) +
geom_col(color = 'black',
width = 0.65,
position = position_dodge(width = 0.9)) +
geom_text(data = finaldf,
aes(x = cat1,
y = count1,
group = cat2,
label = scales::percent(fakeperc/100, accuracy = 0.01)),
inherit.aes = FALSE,
color = 'black',
position = position_dodge(0.9),
hjust = -0.1,
size = 3) +
scale_y_continuous(limits = c(0,50), breaks = c(0,10,20,30,40,50)) +
scale_fill_brewer(palette = "Set3") +
theme_classic() +
coord_flip()
I cleaned up a bit the code (according to my taste)
I changed scale_y_numeric to scale_y_continuous (since count1 should be numeric)
I used coord_flip() to make it more readable
I used scales::percent to write percentage numbers
(don't know why you set up limits from 0 to 50 but I left them as I suppposed they were intended)
If you don't want to use coor_flip:
finaldf$count1 <- as.numeric(finaldf$count1)
ggplot(data = finaldf,
aes(x = cat1,
y = count1,
fill = cat2,
group = cat2)) +
geom_col(color = 'black',
width = 0.65,
position = position_dodge(width = 0.9)) +
geom_text(data = finaldf,
aes(x = cat1,
y = count1,
group = cat2,
label = scales::percent(fakeperc/100, accuracy = 0.01)),
inherit.aes = FALSE,
color = 'black',
position = position_dodge(0.9),
hjust = -0.1,
angle = 90,
size = 3) +
scale_y_continuous(limits = c(0,50), breaks = c(0,10,20,30,40,50)) +
scale_fill_brewer(palette = "Set3") +
theme_classic()
Is this what you are looking for:
library(ggplot2)
#Code
ggplot(data=finaldf,aes(x=cat2, y=count1,
fill=cat2,group=cat2)) +
geom_bar(stat='identity',color='black',
position=position_dodge(width=1))+
scale_fill_brewer(palette="Set3") +
theme_bw() +
geom_text(aes(x=cat2,y=count1,group=cat2,
label=format(paste(round(fakeperc),"%",sep = ""))),inherit.aes = F,
color='black',position=position_dodge(1),
size=3,vjust=-0.5)+
facet_wrap(.~cat1,scales = 'free_x',nrow = 1,strip.position = 'bottom')+
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
legend.position = 'top',
strip.background = element_blank(),
panel.spacing = unit(2, "lines"),
panel.grid = element_blank())+
guides(fill = guide_legend(nrow = 1))
Output:

labels in bar chart touches the top horizontal line

I am trying to create a bar chart within a shiny context. Everything looks good but the labels. As you can see in the below image, some of the labels are hidden behind the top horizontal line.
Diff_plot <- reactive({
ggplot(Diff_data(), aes(x =Difficulty_Type, y = Percentage, fill=County.y)) + geom_bar(stat =
"identity",
position = position_dodge()
) +
scale_fill_manual(values=cbbPalette)+
geom_text(
aes(label = Percentage2),
vjust = 0,
colour = "black",
position = position_dodge(width=0.9),
fontface = "bold",
size=4,
angle = 90,
hjust = 0
) +
labs(
x = "",
y = "Frequecny",
face = "bold"
) +
theme_bw() + scale_y_continuous(labels = scales::comma) +
theme(plot.title = element_text(
hjust = 0.5,
size = 15,
colour = "Black",
face = "bold"
)
you can use a combination of hjust and vjust to set the text on top of your bargraph.
Using hjust = -1, you will get more space between the top of your bargraph and the text. If your text is hidden by the top horizontal line, you can increase limits of y axis by using ylim
df <- data.frame(X = LETTERS[1:3],
Y = sample(1:10,3),
labels = letters[4:6])
library(ggplot2)
ggplot(df,aes(x = X, y = Y, label = labels))+
geom_col()+
geom_text(angle = 90, hjust = -1, vjust = 0.5)+
ylim(0,6.5)

Can this type of plot be done with ggplot2?

I am using R and ggplot2 to do some plots for publishing purposes. I have come across this plot and I would like to replicate it using ggplot2. However, I have never seen a plot like this made using ggplot2.
Can it be done with ggplot2? What about the text below the bars? I guess these will have to be hard coded in the ggplot2 codes. And how do you align those text?
This gets fairly close:
# Generate sample data (I'm too lazy to type out the full labels)
df <- data.frame(
perc = c(60, 36, 44, 41, 42, 57, 34, 52),
type = rep(c("blue", "green"), 4),
label = rep(c(
"Individual reports created as needed",
"Regular reports on single topics",
"Analytics using data integrated from multiple systems",
"Business unit-specific dashboards and visuals"), each = 2))
library(ggplot2)
ggplot(df, aes(1, perc, fill = type)) +
geom_col(position = "dodge2") +
scale_fill_manual(values = c("turquoise4", "forestgreen"), guide = FALSE) +
facet_wrap(~ label, ncol = 1, strip.position = "bottom") +
geom_text(
aes(y = 1, label = sprintf("%i%%", perc)),
colour = "white",
position = position_dodge(width = .9),
hjust = 0,
fontface = "bold") +
coord_flip(expand = F) +
theme_minimal() +
theme(
axis.title = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
strip.text = element_text(angle = 0, hjust = 0, face = "bold"))
A few explanations:
We use dodged bars and matching dodged labels with position = "dodge2" (note that this requires ggplot_ggplot2_3.0.0, otherwise use position = position_dodge(width = 1.0)) and position = position_dodge(width = 0.9), respectively.
We use facet_wrap and force a one-column layout; strip labels are moved to the bottom.
We rotate the entire plot with coord_flip(expand = F), where expand = F ensures that left aligned (hjust = 0) facet strip texts align with 0.
Finally we tweak the theme to increase the overall aesthetic similarity.
You can try using the data from the other answer. Differences are: we use scales::percent to draw percents. We use ggpubr::theme_transparent() theme to tweak as less as possible.
df$perc <- c(.60, .36, .44, .41, .42, .57, .34, .52)
ggplot(df, aes(label, perc, label=scales::percent(round(perc,2)),fill= factor(type))) +
geom_col(position = position_dodge(0.9), show.legend = F) +
geom_text(aes(y=0), position = position_dodge(0.9), size=5, hjust=-0.1, color="white", fontface="bold") +
scale_y_continuous("",labels = scales::percent) +
coord_flip(expand = F) +
facet_wrap(~label,scales = "free", strip.position = "bottom", ncol = 1) +
ggpubr::theme_transparent() +
xlab("") +
theme(strip.background = element_blank(),
strip.text = element_text(size = 12, face = "bold",hjust=0))
Maybe using facet wrap and adjusting the style?
dat <- data.frame(perc = c(60, 20, 90, 30), col = rep(c("gr1", "gr2"), 2),
text = c(rep("text1", 2), rep("text2", 2)))
ggplot(dat, aes(y = perc, x = col, fill = col)) +
geom_bar(stat = "identity", position = "dodge") +
coord_flip() +
facet_wrap(~text, strip.position = "bottom", ncol = 1)

How do I reverse the order in which error bars appear using geom_errorbar() in R?

I have the following example plot:
test <- data.frame("Factor" = as.factor(c("O", "C", "A")),
b = c(0.18, .34, .65, -.13, .38, .26),
lower95 = c(-.1, .09, .34, -.52, .10, -.02),
upper95 = c(.48, .58, .98, .26, .67, .56),
group = factor(c("Experiment 1","Experiment 2")))
test$Factor <- factor(test$Factor, as.character(test$Factor))
test$group <- factor(test$group, as.character(test$group))
ggplot(test, aes(Factor, b, colour = group)) +
geom_errorbar(aes(ymin = lower95, ymax = upper95),
size = 1,
width = .5,
position = 'dodge') +
geom_hline(yintercept = 0) +
ylim(-1.25, 1.25) +
coord_flip() +
theme_bw() +
ggtitle("Title") +
theme(
axis.text=element_text(size = 20),
axis.title=element_text(size = 18),
plot.title = element_text(size = 20, face = "bold"),
axis.text.y=element_text(size = 12)
)
As you'll see, the error bars appear in the reverse order (from top to bottom) as they do in the legend. I would like Experiment 1 error bars to appear above Experiment 2 error bars.
I have tried
ggplot(test, aes(Factor, b, colour = forcats::fct_rev(groups)
But this reverses the order of the group labels in the legend, not the order of the colours in the legend–which is what would work. I have also tried reversing the order in which I enter them in the data frame and this does not solve the problem.
I would appreciate some help!
Re-factoring will change the order of the plot, but, as you saw, also changes the order of the legend. In addition to reversing the levels of group, you can reverse the order the legend is displayed with the reverse argument in guide_legend.
ggplot(test, aes(Factor, b, colour = forcats::fct_rev(group))) +
geom_errorbar(aes(ymin = lower95, ymax = upper95),
size = 1,
width = .5,
position = 'dodge') +
geom_hline(yintercept = 0) +
ylim(-1.25, 1.25) +
coord_flip() +
theme_bw() +
ggtitle("Title") +
theme(
axis.text=element_text(size = 20),
axis.title=element_text(size = 18),
plot.title = element_text(size = 20, face = "bold"),
axis.text.y=element_text(size = 12)
) +
guides(color = guide_legend(reverse = TRUE) )
If you are using scale_color_discrete or scale_color_manual to control other scale elements like the legend name, you can use guide_legend there instead of via guides.
+
scale_color_discrete(name = "Experiment", guide = guide_legend(reverse = TRUE) )
Do you mean something like this?
test$Factor <- factor(test$Factor, levels = rev(levels(test$Factor)));
test$group <- factor(test$group, levels = rev(levels(test$group)));
ggplot(test, aes(Factor, b, colour = group)) +
geom_errorbar(aes(ymin = lower95, ymax = upper95),
size = 1,
width = .5,
position = 'dodge') +
geom_hline(yintercept = 0) +
ylim(-1.25, 1.25) +
coord_flip() +
theme_bw() +
ggtitle("Title") +
theme(
axis.text=element_text(size = 20),
axis.title=element_text(size = 18),
plot.title = element_text(size = 20, face = "bold"),
axis.text.y=element_text(size = 12)
)
I'm not entirely clear on whether you want to reverse the ordering of test$Factor as well; just (un)comment the corresponding line depending on what you're after.

Resources