Draw points border in a customized plot [duplicate] - r

This question already has answers here:
Place a border around points
(5 answers)
Closed 1 year ago.
I have a dataset like this:
Year<-rep(2001:2005, each = 5)
name<-c("John","Ellen","Mark","Randy","Luisa")
Name<-c(rep(name,5))
Value<-sample(seq(0,25,by=1),25)
mydata<-data.frame(Year,Name,Value)
And my plot looks like this:
p <- ggplot(mydata, aes(x=Year, y=reorder(Name, desc(Name)), size = Value)) +
geom_point(aes(colour = Value,
alpha = I(as.numeric(Value > 0))))
p <- p + scale_colour_viridis_c(option = "D", direction = -1,
limits = c(1, 25)) +
scale_size_area(guide = "none") +
ylab("Name") +
theme(axis.line = element_blank(),
axis.text.x=element_text(size=11,margin=margin(b=10),colour="black"),
axis.text.y=element_text(size=13,margin=margin(l=10),colour="black",
face="italic"),
axis.ticks = element_blank(),
axis.title=element_text(size=18,face="bold"),
panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
panel.background = element_blank(),
legend.text = element_text(size=14),
legend.title = element_text(size=18))
I would like to improve it in two ways but I couldn't figure out how.
I would like to add a black border around points. I know I should use pch>20 and specify colour, but because my colours are mapped to a feature of the dataset (they depend on value, in this case), I don't know exactly how to do that. Note that value = 0 points are not plotted. Easy stratagems such as plotting bigger black points under my points seem utopic for me.
I would like to change the breaks of the scale (e.g., instead of having breaks every 5, I'd like to have breaks every 2.5), but it is a continuous scale, and I'm not sure how to do that.
I am not very familiar with ggplo2, thus any help would be appreciated!

You can indeed use a shape >20, e.g. I use shape=21 here. Then you need to change your scale_color_ to scale_fill_, because the color is now black (it is the border of the shape).
For breaks, you could just specify them in the scale itself. Combining both:
ggplot(mydata, aes(x=Year, y=reorder(Name, desc(Name)), size = Value)) +
geom_point(aes(fill = Value,
alpha = I(as.numeric(Value > 0))), shape=21, color = "black") +
scale_fill_viridis_c(option = "D", direction = -1,
limits = c(1, 25), breaks=seq(1, 25, 2.5)) +
scale_size_area(guide = "none") +
ylab("Name") +
theme(axis.line = element_blank(),
axis.text.x=element_text(size=11,margin=margin(b=10),colour="black"),
axis.text.y=element_text(size=13,margin=margin(l=10),colour="black",
face="italic"),
axis.ticks = element_blank(),
axis.title=element_text(size=18,face="bold"),
panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
panel.background = element_blank(),
legend.text = element_text(size=14),
legend.title = element_text(size=18))

Related

Combining and resizing barplot and ggplot

I have two plots I would like to combine. My data looks like this:
Year<-rep(2001:2005, each = 5)
name<-c("John","Ellen","Mark","Randy","Luisa")
Name<-c(rep(name,5))
Value<-sample(seq(0,25,by=1),25)
mydata<-data.frame(Year,Name,Value)
This is the first barplot:
tot<-aggregate(mydata$Value,list(mydata$Year),FUN=sum)
tot_y<-tot$x
tot_x<-tot$Group.1
tot_barplot <- ggplot(tot, aes(x=tot_x,y=tot_y)) +
geom_bar(stat = "identity",fill="#73D055FF") +
scale_y_continuous(limits = c(0, 125), breaks = seq(0, 125, by = 25)) +
#xlab("Pathways") +
#ylab("N° of species") +
theme(axis.line = element_blank(),
axis.text.x=element_blank(),
axis.text.y=element_text(size=14,margin=margin(l=10),colour="black"),
axis.ticks = element_blank(),
axis.title=element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank())
tot_barplot
And this is the second plot:
p <- ggplot(mydata, aes(x=Year, y=Name, size = Value)) +
geom_point(aes(fill = Value,
alpha = I(as.numeric(Value > 0))), shape=21, colour = "black") +
scale_fill_viridis_c(option = "D", direction = -1,limits = c(1, 25), breaks=seq(1, 25, 5))+
scale_size_area(guide = "none") +
ylab("Name") +
theme(axis.line = element_blank(),
axis.text.x=element_text(size=11,margin=margin(b=10),colour="black"),
axis.text.y=element_text(size=13,margin=margin(l=10),colour="black",
face="italic"),
axis.ticks = element_blank(),
axis.title=element_text(size=18,face="bold"),
panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
panel.background = element_blank(),
legend.text = element_text(size=14),
legend.title = element_text(size=18))
p
I combine them like this:
grid.arrange(arrangeGrob(tot_barplot,p,nrow=2))
Now I would like to re-size the barplot to fit it better to the second plot (imagine that the original data produce a wider barplot where the bars start above the Name and end above the legend Value). I would like the bars of the barplot to be exactly centred above the line of points and the Year, but I am not very familiar with ggplot aesthetics.
Any suggestion would be appreciated. Thanks!

How to change the plot.background in Donut ggplot graph?

How to change the plot.background in a 'geom_rect()' + 'coord.polar()' in a Donut ggplot graph?
I dont know what I´m missing, but I´w working in html black background style and needing to set panel as well plot background to black, but the graph sides of my ggplot are white and I need to know which attribute or command I need to use to turn sides to black too.
Below my code:
my_df %>%
ggplot(aes(ymax=max, ymin=min, xmax=4, xmin=3,fill=ResultCode)) +
geom_rect() +
geom_label( x=3.5, aes(y=labelPosition, label=label), size=4, color="white") +
coord_polar(theta="y") +
xlim(c(2, 4)) +
theme_void() +
theme(legend.position="none",
plot.background=element_rect(fill = "black"),
panel.background = element_rect(fill = "black"),
panel.border = element_blank(),
legend.key = element_blank(),
axis.ticks = element_blank(),
axis.text.y = element_blank(),
panel.grid = element_blank())
Below the resulted graph (see the "white" sides at right and left I need to fill with black)
The problem here is that ggplot by default calls grid::grid.newpage before drawing. This creates a blank (white) screen. It will then set up a square viewport to fit your plotting window because you are using coord_polar. Once it has done this, it considers the square area to be "the" plotting window. In a sense then, ggplot has no knowledge or control over these white areas. No theme element can touch it.
The solution is to explicitly call grid.newpage yourself, draw a black background manually, and then explicitly print your ggplot using the parameter newpage = FALSE. You could alternatively set the grid gpar parameters so that the background is black by default, but this is likely to have undesired side effects later on.
Here's a reprex with some made-up data:
my_df <- data.frame(max = c(160, 320), min = c(0, 161),
ResultCode = c("A","B"),
labelPosition = c(80, 240), label = c("A", "B"))
p <- my_df %>%
ggplot(aes(ymax=max, ymin=min, xmax=4, xmin=3,fill=ResultCode)) +
geom_rect() +
geom_label( x=3.5, aes(y=labelPosition, label=label), size=4, color="white") +
coord_polar(theta="y") +
xlim(c(2, 4)) +
theme(legend.position="none",
plot.background = element_rect(fill = "black", color = "black"),
panel.background = element_rect(fill = "black", color = "black"),
plot.margin = margin(0,0,0,0),
panel.border = element_blank(),
legend.key = element_blank(),
axis.ticks = element_blank(),
axis.text.y = element_blank(),
panel.grid = element_blank())
grid::grid.newpage()
grid::grid.draw(grid::rectGrob(gp = grid::gpar(fill = "black")))
print(p, newpage = FALSE)

Arrange faceted plots in a grid - how to completely remove facet labels to avoid overlapping

I am a bit stuck with the following: I want to arrange multiple (gg)plots into a grid with cowplot::plot_grid. Below is an example with two ggplots (g_bottom and g_top), both faceted. The bottom one has the facet labels deleted as they are redundant. However, there seems to remain the contour of the background or so, acting as cutting with a white line the top plot (see image below).
How could I fix this?
What have I tried so far:
Instead of strip.background = element_blank() I also tried strip.background = element_rect(fill = NA, color = NA) in theme, but with no success.
If I set rect = element_blank(), it somehow works, but I lose the entire plot border. I was then hopping that rect = element_rect(fill = "transparent", colour = NA) would do it, but still no success. I also just tried colour = NULL or colour = "transparent" also with no success.
library(ggplot2)
library(cowplot)
g <- ggplot(mpg, aes(class)) +
geom_bar() +
facet_grid(. ~ year) +
theme_bw()
g_bottom <- g +
theme(
strip.text = element_blank(),
strip.background = element_blank(),
# strip.background = element_rect(fill = NA, color = NA) # didn't work either
# Was hoping that this will do the trick, bot no success:
rect = element_rect(fill = "transparent", color = NA)
)
g_top <- g +
labs(x = element_blank()) +
theme(
axis.text.x = element_blank(),
axis.ticks.x = element_blank()
)
plot_grid(g_top, NULL, g_bottom,
# used NULL to be able to tweak spacing between plots with rel_heights
align = "hv",
nrow = 3,
rel_heights = c(1, -0.2, 1))
I could go around the problem by not faceting and creating each of the 4 plots individually, but maybe there is a more straightforward solution with some theme argument which I'm too blinded to see any-further...
Eventually, using rect = element_blank() in theme when making g_bottom and then adding panel.border = element_rect(colour = "black") seems to do the trick. I still fail to understand why the initial trials didn't work as expected.
library(ggplot2)
library(cowplot)
g <- ggplot(mpg, aes(class)) +
geom_bar() +
facet_grid(. ~ year) +
theme_bw()
g_bottom <- g +
theme(
strip.text = element_blank(),
rect = element_blank(),
panel.border = element_rect(colour = "black")
)
g_top <- g +
labs(x = element_blank()) +
theme(
axis.text.x = element_blank(),
axis.ticks.x = element_blank()
)
plot_grid(g_top, NULL, g_bottom + theme(panel.border = element_rect(colour = "black")),
align = "hv",
nrow = 3,
rel_heights = c(1, -0.2, 1))

ggplot2: Boxplots with points and fill separation [duplicate]

This question already has answers here:
ggplot2 - jitter and position dodge together
(2 answers)
Closed 6 years ago.
I have a data which can be divaded via two seperators. One is year and second is a field characteristics.
box<-as.data.frame(1:36)
box$year <- c(1996,1996,1996,1996,1996,1996,1996,1996,1996,
1997,1997,1997,1997,1997,1997,1997,1997,1997,
1996,1996,1996,1996,1996,1996,1996,1996,1996,
1997,1997,1997,1997,1997,1997,1997,1997,1997)
box$year <- as.character(box$year)
box$case <- c(6.40,6.75,6.11,6.33,5.50,5.40,5.83,4.57,5.80,
6.00,6.11,6.40,7.00,NA,5.44,6.00, NA,6.00,
6.00,6.20,6.40,6.64,6.33,6.60,7.14,6.89,7.10,
6.73,6.27,6.64,6.41,6.42,6.17,6.05,5.89,5.82)
box$code <- c("L","L","L","L","L","L","L","L","L","L","L","L",
"L","L","L","L","L","L","M","M","M","M","M","M",
"M","M","M","M","M","M","M","M","M","M","M","M")
colour <- factor(box$code, labels = c("#F8766D", "#00BFC4"))
In boxplots, I want to display points over them, to see how data is distributed. That is easily done with one single boxplot for every year:
ggplot(box, aes(x = year, y = case, fill = "#F8766D")) +
geom_boxplot(alpha = 0.80) +
geom_point(colour = colour, size = 5) +
theme(text = element_text(size = 18),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.x = element_blank(),
legend.position = "none")
But it become more complicated as I add fill parameter in them:
ggplot(box, aes(x = year, y = case, fill = code)) +
geom_boxplot(alpha = 0.80) +
geom_point(colour = colour, size = 5) +
theme(text = element_text(size = 18),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.x = element_blank(),
legend.position = "none")
And now the question: How to move these points to boxplot axes, where they belong? As blue points to blue boxplot and red to red one.
Like Henrik said, use position_jitterdodge() and shape = 21. You can clean up your code a bit too:
No need to define box, then fill it piece by piece
You can let ggplot hash out the colors if you wish and skip constructing the colors factor. If you want to change the defaults, look into scale_fill_manual and scale_color_manual.
box <- data.frame(year = c(1996,1996,1996,1996,1996,1996,1996,1996,1996,
1997,1997,1997,1997,1997,1997,1997,1997,1997,
1996,1996,1996,1996,1996,1996,1996,1996,1996,
1997,1997,1997,1997,1997,1997,1997,1997,1997),
case = c(6.40,6.75,6.11,6.33,5.50,5.40,5.83,4.57,5.80,
6.00,6.11,6.40,7.00,NA,5.44,6.00, NA,6.00,
6.00,6.20,6.40,6.64,6.33,6.60,7.14,6.89,7.10,
6.73,6.27,6.64,6.41,6.42,6.17,6.05,5.89,5.82),
code = c("L","L","L","L","L","L","L","L","L","L","L","L",
"L","L","L","L","L","L","M","M","M","M","M","M",
"M","M","M","M","M","M","M","M","M","M","M","M"))
ggplot(box, aes(x = factor(year), y = case, fill = code)) +
geom_boxplot(alpha = 0.80) +
geom_point(aes(fill = code), size = 5, shape = 21, position = position_jitterdodge()) +
theme(text = element_text(size = 18),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.x = element_blank(),
legend.position = "none")
I see you've already accepted #JakeKaupp's nice answer, but I thought I would throw in a different option, using geom_dotplot. The data you are visualizing is rather small, so why not forego the boxplot?
ggplot(box, aes(x = factor(year), y = case, fill = code))+
geom_dotplot(binaxis = 'y', stackdir = 'center',
position = position_dodge())

move legend title in ggplot2

I have been trying to shift my legend title across to be centered over the legend contents using the guide function. I've been trying to use the following code:
guides(colour=guide_legend(title.hjust = 20))
I thought of trying to make a reproducable example, but I think the reason it's not working has something to do with the above line not matching the rest of my code specifically. So here is the rest of the code I'm using in my plot:
NH4.cum <- ggplot(data=NH4_by_Date, aes(x=date, y=avg.NH4, group = CO2, colour=CO2)) +
geom_line(aes(linetype=CO2), size=1) + #line options
geom_point(size=3) + #point symbol sizes
#scale_shape_manual(values = c(1, 16)) + #manually choose symbols
theme_bw()+
theme(axis.text.x=element_text(colour="white"), #change x axis labels to white.
axis.title=element_text(size=12),
axis.title.x = element_text(color="white"), #Change x axis label colour to white
panel.border = element_blank(), #remove box boarder
axis.line.x = element_line(color="black", size = 0.5), #add x axis line
axis.line.y = element_line(color="black", size = 0.5), #add y axis line
legend.key = element_blank(), #remove grey box from around legend
legend.position = c(0.9, 0.6))+ #change legend position
geom_vline(xintercept=c(1.4,7.5), linetype="dotted", color="black")+ #put in dotted lines for season boundaries
scale_color_manual(values = c("#FF6600", "green4", "#0099FF"),
name=expression(CO[2]~concentration~(ppm))) + #manually define line colour
scale_linetype_manual(guide="none", values=c("solid", "solid", "solid")) + #manually define line types
scale_shape_manual(values = c(16, 16, 16)) + #manually choose symbols
guides(colour=guide_legend(title.hjust = 20))+
scale_y_continuous(expand = c(0, 0), limits = c(0,2200), breaks=seq(0,2200,200))+ #change x axis to intercept y axis at 0
xlab("Date")+
ylab(expression(Membrane~available~NH[4]^{" +"}~-N~(~mu~g~resin^{-1}~14~day^{-1})))+
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
geom_errorbar(aes(ymin = avg.NH4 - se.NH4, #set y error bars
ymax = avg.NH4 + se.NH4),
width=0.1)
I have tried doing the following instead with no luck:
guides(fill=guide_legend(title.hjust=20)
I have also adjusted the hjust value from values between -2 to 20 just to see if that made a difference but it didn't.
I'll try to attach a picture of the graph so far so you can see what I'm talking about.
I've looked through all the questions I can on stack overflow and to the best of my knowledge this is not a duplicate as it's specific to a coding error of my own somewhere.
Thank-you in advance!!
The obvious approach e.g.
theme(legend.title = element_text(hjust = .5))
didn't work for me. I wonder if it is related to this open issue in ggplot2. In any case, one manual approach would be to remove the legend title, and position a new one manually:
ggplot(mtcars, aes(x = wt, y = mpg, colour = factor(cyl))) +
geom_point() +
stat_smooth(se = FALSE) +
theme_bw() +
theme(legend.position = c(.85, .6),
legend.title = element_blank(),
legend.background = element_rect(fill = alpha("white", 0)),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank()) +
annotate("text", x = 5, y = 27, size = 3,
label = "CO[2]~concentration~(ppm)", parse = TRUE)
Output:

Resources