How to reduce whitespace in ggplot plot area? - r

I have a pie graph. I want to reduce the white space in the panel. I made the background colored green for you to see the area occupied by the white space.
Here is my data
structure(list(PER = c(34.4413912651734, 64.2857433622907, 1.2728653725359
), CAT = structure(1:3, .Label = c("Yes", "No", "Don’t know/Refused"
), class = "factor")), row.names = c("Yes", "No", "Don’t know/Not sure"
), class = "data.frame")
Here is what I tried so far:
xfall <- ggplot(table_fall_FRQ, aes(x="", y=PER, fill=CAT)) +
geom_bar(width = 1, size = 1, stat = "identity") +
coord_polar("y") +
geom_text(aes(label = paste0(round(PER), "%")),
position = position_stack(vjust = 0.5), color="white",
size=14) +
labs(#title="",
#subtitle="",
caption="n= respondents with income less than $60,000 year \nSource: Sample",
x="",
y="") +
scale_fill_viridis(discrete=TRUE) +
guides(fill = guide_legend(reverse = FALSE)) +
theme_classic() +
theme(axis.text.x = element_blank(),
axis.line.x = element_blank(),
axis.ticks.x = element_blank(),
axis.line = element_blank(),
axis.text=element_text(size=14, color="white"),
#axis.title=element_text(size=14,face="bold"),
#panel.grid.major = element_blank(),
panel.spacing.x=unit(0, "lines"),
panel.spacing.y=unit(0, "lines"),
legend.position="top",
legend.box.spacing = unit(0.1, 'cm'),
legend.margin = margin(0, 0, 0, 0, "cm"),
legend.title = element_blank(),
plot.caption = element_text(hjust = 0, lineheight=1.5),
#plot.subtitle = element_text(color="blue"),
plot.background = element_rect(fill="green"),
plot.margin = margin(0, 0, 0, 0, "cm")
)
xfall
Which part shall I update in order for the white space to shrink? id like my legend and caption to get closer to the pie.

the post of Rui helped me find it.
xfall <- ggplot(table_fall_FRQ, aes(x="", y=PER, fill=CAT)) +
geom_bar(width = 1, size = 1, stat = "identity") +
coord_polar("y") +
geom_text(aes(label = paste0(round(PER), "%")),
position = position_stack(vjust = 0.5), color="white",
size=14) +
labs(#title="",
#subtitle="",
caption="n= respondents with income less than $60,000 year \nSource: Sample",
x="",
y="") +
scale_fill_viridis(discrete=TRUE) +
guides(fill = guide_legend(reverse = FALSE)) +
theme_classic() +
theme(axis.text = element_blank(),
axis.ticks.length = unit(0, "mm"),
axis.line = element_blank(),
#axis.title=element_text(size=14,face="bold"),
#panel.grid.major = element_blank(),
panel.spacing.x=unit(0, "lines"),
panel.spacing.y=unit(0, "lines"),
legend.position="top",
legend.box.spacing = unit(-1, 'cm'),
legend.margin = margin(0, 0, 0, 0, "cm"),
legend.title = element_blank(),
plot.caption = element_text(hjust = 0,margin = unit(c(-15,0,0,0), "mm")),
#plot.subtitle = element_text(color="blue"),
plot.background = element_rect(fill="green"),
plot.margin = margin(0, 0, 0, 0, "cm")
)
xfall
You can further change the position of the caption by using plot.caption and the position of the legend by using a vector, like c(0.5, 0.5) instead of "top".
Hope this is helpfull

Related

How to align caption text with left bar in a bar chart?

I am trying to align the caption text in a bar chart, so that it will start at the same vertical margin as the left bar.
library(ggplot2)
library(tibble)
my_df <-
tibble::tribble(~response, ~estimate,
"little_bit", 0.353477,
"no", 0.307639,
"very", 0.338883)
ggplot(my_df, aes(x = reorder(response, -estimate), y = estimate)) +
geom_bar(stat = "identity", width = 0.9, fill = "royalblue") +
ggtitle("do you like swimming with fish?") +
ylab("") +
labs(caption = "this is my caption") +
theme_minimal() +
theme(
axis.line.x = element_blank(),
axis.line.y = element_blank(),
axis.text.y = element_blank(),
panel.grid = element_blank(),
panel.grid.major=element_blank(),
plot.title = element_text(hjust = 0.5, size = 26),
axis.text.x = element_text(angle = 0, size = 14, margin = margin(t = 0, r = 20, b = 0, l = 0)),
axis.title.x = element_blank(),
legend.title = element_blank(),
plot.caption = element_text(hjust = 0, size = 8),
plot.caption.position = "plot") ## <-- I thought this would help, but no...
Is there a way to align the caption such as the following?
To get your desired result set the caption position to "panel" and remove the expansion of the x-scale:
library(ggplot2)
library(tibble)
my_df <-
tibble::tribble(~response, ~estimate,
"little_bit", 0.353477,
"no", 0.307639,
"very", 0.338883)
ggplot(my_df, aes(x = reorder(response, -estimate), y = estimate)) +
geom_bar(stat = "identity", width = 0.9, fill = "royalblue") +
ggtitle("do you like swimming with fish?") +
scale_x_discrete(expand = c(0, 0)) +
labs(caption = "this is my caption", y = NULL) +
theme_minimal() +
theme(
axis.line.x = element_blank(),
axis.line.y = element_blank(),
axis.text.y = element_blank(),
panel.grid = element_blank(),
panel.grid.major=element_blank(),
plot.title = element_text(hjust = 0.5, size = 26),
axis.text.x = element_text(angle = 0, size = 14, margin = margin(t = 0, r = 20, b = 0, l = 0)),
axis.title.x = element_blank(),
legend.title = element_blank(),
plot.caption = element_text(hjust = 0, size = 8),
plot.caption.position = "panel")
Or, a very common workaround for those cases would be to annotate outside of the plot area. (I am using annotate(geom = "text",...) - you could also use geom_text, but you would only need a data frame for it.)
I personally prefer the annotate option as it is more versatile and generalisable for other purposes as well.
library(ggplot2)
my_df <-
tibble::tribble( ~response, ~estimate, "little_bit", 0.353477, "no", 0.307639, "very", 0.338883)
barwidth <- 0.9
ggplot(my_df, aes(x = reorder(response, -estimate), y = estimate)) +
geom_bar(stat = "identity", width = barwidth, fill = "royalblue") +
annotate(
geom = "text",
x = 1 - barwidth / 2, hjust = 0, # that's the trick
y = -0.1, # play around with y. you could also set it relativ to your bar heights
label = "this is my caption"
) +
coord_cartesian(clip = "off", ylim = c(0, NA)) + # necessary to set axis limits and clip off to annotate beyond
ggtitle("do you like swimming with fish?") +
theme_minimal() +
theme(plot.margin = margin(b = 1, unit = "inch")) # margin randomly chosen. unfortunately also necessary

How to change font and lollipop size?

I want to increase the width of the sticks on my lollipop graph, and increase the size of the font of my y-labels. How would I go about doing that?
df_graph2 <- data.frame(
parameters = c("Cut back spending on food",
"Used up all or most saving",
'Increased credit card debt',
'Took money out of long-term savings',
'Borrowed money from family or friends',
'Pawned or sold possessions'),
values <- c(34.40,26.00,25.50,14.40,12.70,11.30))
df_graph2 %>%
ggplot() + aes(x=parameters, y=values) +
geom_segment( aes(x=parameters, xend=parameters, y=0, yend=values), color="gray82") +
geom_point( color="darkorange", size=4.2, alpha=0.9) +
geom_text(aes(label = paste(values,"%")), hjust = -.3,size=3.8,family="Arial") +
expand_limits(y = 100)+
theme_light() +
coord_flip() +
theme(
plot.margin = margin(1, 1, 4, 1.1, "cm"),
panel.grid.major.y = element_blank(),
axis.text.y = element_text(color = 'black'),
panel.border = element_blank(),
axis.ticks.y = element_blank(),
axis.ticks.x = element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.text.x = element_blank(),
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank()
)
Change the y axis label size using the size parameter inside the element_text call of theme(axis.text.y and change the line width of the lollipops with size = inside geom_segment
ggplot(df_graph2, aes(parameters, values)) +
geom_segment(aes(xend = parameters, y = 0, yend = values),
size = 2, color = "gray82") +
geom_point(color = "darkorange", size = 4.2, alpha = 0.9) +
geom_text(aes(label = paste(values,"%")), hjust = -.3, size=3.8) +
expand_limits(y = 100) +
coord_flip() +
theme_void() +
theme(plot.margin = margin(1, 1, 4, 1.1, "cm"),
axis.text.y = element_text(color = 'black', size = 12, hjust = 1))

Aligning text on horizontal bar chart

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:

How to move legend up closer to the x-axis label in ggplot2

I have am creating a function to create dumbbell graphs with the legend positioned on the bottom. However, it's too far away from the title of the x-axis. I wanted to move it up slightly so that it is 10 pixels below the x-axis.
Here's the code:
vertical_theme = theme_bw(base_family = "Georgia") +
theme(
panel.border = element_rect(color = "black", fill=NA),
axis.title.x = element_text(hjust=0.5, size = 10, margin=margin(t=10, b=10)),
axis.text.y = element_text(size=10, margin=margin(r=10), color="black", hjust=0),
axis.text.x = element_text(size=10, margin=margin(t=10), color="black"),
axis.title.y = element_blank(),
legend.title = element_blank(),
legend.position= "bottom",
legend.text = element_text(size = 10, margin = margin(r = 10)),
panel.grid.major.y = element_blank() ,
panel.grid.minor.y = element_blank(),
panel.grid.major.x = element_line(size=1),
panel.grid.minor.x = element_blank(),
plot.margin = margin(10, 30, 10, 10, "pt"))
dumbbell = function(df) {
ggplot(df, aes(pct_responses, Domain)) +
geom_line(aes(group=Domain)) +
geom_point(aes(shape=race), size=5, color="#3bbae0" ) +
vertical_theme +
scale_shape_manual(labels = c("Black Students", "White Students"),
values=c(15, 19)) +
scale_x_continuous(expand = c(0, 0),
limits=c(0,100),
breaks = seq(0, 100, by=20),
labels = function(x) paste0(x,"%")) +
labs(x = "% of Responses") +
scale_y_discrete(labels = wrap_format(40))
}
dumbbell(df)
Here's a screenshot (labels on y-axis removed because that data isn't public yet):
I tried to adjust the legend.position manually with legend.position = c(0.5, 0) (playing around with various different numbers) but then the legend overlaps with "% of Responses."
Use theme(legend.margin=margin(-10, 0, 0, 0)) to move the legend up. Adjust -10 as needed.

ggplot2 geom_bar: Centering bars

I would really appreciate help with a ggplot2 issue. I've been looking around it for long, so my best chance is now here. I provide a reproducible script.
What I'd need to do is center the bars horizontally. For now, they polarise towards the sides--especially notably on the 2009 and 2012 bars.
Centering them would allow me to freely adjust their width, whereas now I cannot.
This is the current, self-contained code:
install.packages('ggplot2')
library(ggplot2)
# Data
Year = c('2009','2009','2009','2009','2010','2010','2010','2010','2011','2011','2011','2011','2012','2012','2012','2012')
City = c('Kaunas','Vilnius','Kaunas','Vilnius','Kaunas','Vilnius','Kaunas','Vilnius',
'Kaunas','Vilnius','Kaunas','Vilnius','Kaunas','Vilnius','Kaunas','Vilnius')
Busy = c('Peak', 'Peak', 'Off-peak', 'Off-peak', 'Peak', 'Peak', 'Off-peak', 'Off-peak', 'Peak', 'Peak', 'Off-peak',
'Off-peak', 'Peak', 'Peak', 'Off-peak', 'Off-peak')
Result = c(-0.417277550641143, 0.540415934506096, -0.887323992801467, -1.0016151369497, -1.69512596882652,
-0.474180286913426, -1.87972395432173, -1.55647964460481, -1.10385766877877, -3.19261229467907,
-2.11137007243349, -3.24910554029829, -0.949278709972917, -2.22558030912235, -1.3496651478542, -2.59961942855099)
pvalue.asterisks = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, '*', NA, '*', NA, NA, NA, NA)
Results = data.frame(Year, City, Busy, Result, pvalue.asterisks)
str(Results)
Results
# Plot
ggplot(Results, aes(Year, Result, fill=City)) +
ylab(expression(paste(italic('t'), '-value'))) +
facet_grid(list('Busy', 'Year')) + scale_fill_grey(start = 0, end = .6) +
geom_bar(width=2.9, stat = "identity", position = position_dodge(width = 3)) +
scale_y_continuous(expand = c(.035,0)) + scale_x_discrete(expand = c(.7,.4)) +
theme( axis.title.x=element_blank(), axis.text.x = element_blank(),
axis.title.y = element_text(size=19, face="bold", margin = margin(0, 3, 0, 0)),
axis.text.y = element_text(size = 13),
legend.title = element_blank(), legend.text = element_text(size=17),
legend.background = element_rect(fill="white", size=0.1, linetype="solid"),
legend.key.size = unit(1.7,"line"), axis.ticks.x=element_blank(), legend.position = c(.167, .6),
panel.background = element_blank(), plot.title = element_blank(),
legend.margin=margin(c(-.05,.14,.11,.1), unit='cm'),
panel.grid.major.y = element_line(colour = "grey90"),
panel.grid.major.x = element_blank(), plot.margin = unit(c(.05, .1, 0, .1), 'cm'),
strip.text.x = element_text(face='bold', size=15, margin = margin(.2, 0, .2, 0, "cm")),
strip.text.y = element_text(face='bold', size=15, margin = margin(0, .2, 0, .2, "cm")),
strip.background = element_rect(colour="grey48", fill='grey95'), panel.spacing = unit(.08, "lines")) +
geom_text(aes(x=Year, y=Result, label=pvalue.asterisks), vjust=-.01, colour= 'white', size=15, hjust=-.168 )
-- Thank you very much
You just need to add scales = 'free_x' to your script. You can also replace geom_bar(stat = 'identity') with geom_col()
Relevant info taken from ?facet_grid
scales: Are scales shared across all facets (the default, "fixed"), or do they vary across rows ("free_x"), columns ("free_y"), or both rows and columns ("free")?
p1 <- ggplot(Results, aes(Year, Result, fill=City)) +
ylab(expression(paste(italic('t'), '-value'))) +
facet_grid(rows = vars(Busy), cols = vars(Year), scales = 'free_x') +
scale_fill_grey(start = 0, end = .6) +
geom_col(position = position_dodge(width = 0.9)) +
scale_y_continuous(expand = c(.035,0)) +
scale_x_discrete(expand = c(.7,.4))
p1 +
theme( axis.title.x=element_blank(), axis.text.x = element_blank(),
axis.title.y = element_text(size=19, face="bold", margin = margin(0, 3, 0, 0)),
axis.text.y = element_text(size = 13),
legend.title = element_blank(), legend.text = element_text(size=17),
legend.background = element_rect(fill="white", size=0.1, linetype="solid"),
legend.key.size = unit(1.7,"line"), axis.ticks.x=element_blank(), legend.position = c(.167, .6),
panel.background = element_blank(), plot.title = element_blank(),
legend.margin=margin(c(-.05,.14,.11,.1), unit='cm'),
panel.grid.major.y = element_line(colour = "grey90"),
panel.grid.major.x = element_blank(), plot.margin = unit(c(.05, .1, 0, .1), 'cm'),
strip.text.x = element_text(face='bold', size=15, margin = margin(.2, 0, .2, 0, "cm")),
strip.text.y = element_text(face='bold', size=15, margin = margin(0, .2, 0, .2, "cm")),
strip.background = element_rect(colour="grey48", fill='grey95'), panel.spacing = unit(.08, "lines")) +
geom_text(aes(x=Year, y=Result, label=pvalue.asterisks), vjust=-.01, colour= 'white', size=15, hjust=-.168 )
#> Warning: Removed 14 rows containing missing values (geom_text).
Created on 2018-09-20 by the reprex package (v0.2.1.9000)
If you remove the theme stuff you will see the problem, the X axis is years, and it's attempting to plot each one on the x-value for that year. One way to fix this is to set the scales parameter to facet_grid to be "free_x".
facet_grid(list('Busy', 'Year'), scales="free_x")
and then you only have to adjust the sizing of the bars.
geom_bar(width=0.5, stat = "identity", position = "dodge")

Resources