Prevent Background Image from Covering Plot - r

I am generating bubble charts from NBA shot data clusters. The final form of the data is:
Where Group.1 is the index of the cluster, ad.SHOT_MADE_FLAG is the field goal percent for the cluster, coords.x1 and x2 are the mean x and y coordinates of the points in that cluster, and x is the number of shots (x and y points) in that cluster.
I am plotting the data with the following:
courtImg.URL <- "https://thedatagame.files.wordpress.com/2016/03/nba_court.jpg"
court <- rasterGrob(readJPEG(getURLContent(courtImg.URL)),
width=unit(1,"npc"), height=unit(1,"npc"))
p6 <- ggplot(final, aes(x = final$coords.x1, y = final$coords.x2, size =
final$x,fill=final$ad.SHOT_MADE_FLAG)) +
geom_point(shape = 21) +
annotation_custom(court, -250, 250, -52, 418) +
scale_x_continuous() +
coord_fixed() +
scale_fill_gradientn(colours = c("Blue","Red")) +
theme(line = element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
legend.title = element_blank(),
plot.title = element_text(size = 17, lineheight = 1.2, face = "bold")) +
ggtitle("Stephen Curry Shot Chart")
p6
This outputs the following chart
I am wanting to solve two issues with this. First the background image is covering up the majority of the data. Second, I want to only show the plot below the 418 point on the y axis. I dont want to show shots from the backcourt as they aren't as relevant. Just for reference, when I remove the annotation_custom() line, it shows the following plot:
So the implementation of the annotation_custom line appears to be part of the problem. Any help would be greatly appreciated. Thanks!

ggplot2 draws plot layers in the order you specify them. To move the image of the court below the points, put it first in the drawing order. The other fix that might make your plot a little nicer is to make the panel background transparent so that you can see the points on top of the image, which I assume is what you're going for.
You can set the ends of the plots using the limits argument in scale_y_continuous().
Updated plotting code:
p6 <- ggplot(final, aes(x = final$coords.x1, y = final$coords.x2, size =
final$x,fill=final$ad.SHOT_MADE_FLAG)) +
annotation_custom(court, -250, 250, -52, 418) +
geom_point(shape = 21) +
scale_x_continuous() +
scale_y_continuous(limits=c(-52,418)) +
coord_fixed() +
scale_fill_gradientn(colours = c("Blue","Red")) +
theme(line = element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
legend.title = element_blank(),
panel.background = element_rect(fill="transparent"),
plot.title = element_text(size = 17, lineheight = 1.2, face = "bold")) +
ggtitle("Stephen Curry Shot Chart")
p6

Related

Adjust grid lines in ggplot+geom_tile (heatmap) or geom_raster

This heatmap has a grid builtin, which I am failing to find the way to customize.
I want to preserve horizontal lines in the grid, if possible increase thickness, and disable vertical lines. Each row should look as a continuous time-serie where data is present and blank where it is not.
Either adding vertical/horizontal lines on-top would possibly cover some data, because of that grid lines, or controlled gaps between tiny rectangles, is preferable.
Alternativelly, geom_raster doesn't shows any grid at all. With which I would need to add the horizontal lines of the grid.
I tried changing linetype, the geom_tile argument, which does seem to change the type or allow to fully disable it with linetype=0, fully disabling the grid, but it wouldn't allow to preserve horizontal grid-lines. I didn't saw any changes by modifying the size argument.
This is the code generating the plot as above:
ggplot( DF, aes( x=rows, y=name, fill = value) ) +
#geom_raster( ) +
geom_tile( colour = 'white' ) +
scale_fill_gradient(low="steelblue", high="black",
na.value = "white")+
theme_minimal() +
theme(
legend.position = "none",
plot.margin=margin(grid::unit(0, "cm")),
#line = element_blank(),
#panel.grid = element_blank(),
panel.border = element_blank(),
panel.grid = element_blank(),
panel.spacing = element_blank(),
#panel.grid = element_line(color="black"),
#panel.grid.minor = element_blank(),
plot.caption = element_text(hjust=0, size=8, face = "italic"),
plot.subtitle = element_text(hjust=0, size=8),
plot.title = element_text(hjust=0, size=12, face="bold")) +
labs( x = "", y = "",
#caption= "FUENTE: propia",
fill = "Legend Title",
#subtitle = "Spaces without any data (missing, filtered, etc)",
title = "Time GAPs"
)
I tried to attach DF %>% dput but I get Body is limited to 30000 characters; you entered 203304. If anyone is familiar with a similar Dataset, please advise.
Additionally,
There are 2 gaps at left&right of the plot area, one is seen inbetween the y-axis, and at the right you can see the X-axis outbounding, and are not controlled by a plot.margin argument.
I would want to set the grid to a thicker line when month changes.
The following data set has the same names and essential structure as your own, and will suffice for an example:
set.seed(1)
DF <- data.frame(
name = rep(replicate(35, paste0(sample(0:9, 10, T), collapse = "")), 100),
value = runif(3500),
rows = rep(1:100, each = 35)
)
Let us recreate your plot with your own code, using the geom_raster version:
library(ggplot2)
p <- ggplot( DF, aes( x=rows, y=name, fill = value) ) +
geom_raster( ) +
scale_fill_gradient(low="steelblue", high="black",
na.value = "white") +
theme_minimal() +
theme(
legend.position = "none",
plot.margin=margin(grid::unit(0, "cm")),
panel.border = element_blank(),
panel.grid = element_blank(),
panel.spacing = element_blank(),
plot.caption = element_text(hjust=0, size=8, face = "italic"),
plot.subtitle = element_text(hjust=0, size=8),
plot.title = element_text(hjust=0, size=12, face="bold")) +
labs( x = "", y = "", fill = "Legend Title", title = "Time GAPs")
p
The key here is to realize that discrete axes are "actually" numeric axes "under the hood", with the discrete ticks being placed at integer values, and factor level names being substituted for those integers on the axis. That means we can draw separating white lines using geom_hline, with values at 0.5, 1.5, 2.5, etc:
p + geom_hline(yintercept = 0.5 + 0:35, colour = "white", size = 1.5)
To change the thickness of the lines, simply change the size parameter.
Created on 2022-08-01 by the reprex package (v2.0.1)

adding a line break using ggplot to the x-axis text

enter image description hereI'm reading in a csv file and using ggplot to make a box plot and having issues with the size of the text on the x axis. I can't reduce the text size because I am reducing the over all image for a manuscript and this is the optimal size to make the axes visible. I'd like to have the genotype names below each box plot on the x axis, I've angled genotype names on the axis, but it still doesn't seem to be enough and looks a bit awkward. I'd like to add a line break for at least the longest genotype (4-67/Chrimson), but I don't think I am doing this right. I've tried setting new labels using in the scale_x_discrete and also in the axis.text.x but under both conditions, it either skips over that variable or ignores the command.
FYI: the data frame has two variables, group activity and genotype and genotype has 4 levels.
Thank you in advance!!
Here's my code so far..
dat5=read.csv("Time Point 120 Raw Data C-Test.csv")
plot5<- ggplot(dat5, aes(x = Genotype, y = Group.Activity, col = Genotype, fill = Genotype, ymin= -40, ymax = 50)) +
geom_boxplot(fatten = 1, lwd = .5, alpha = .6) +
# reorder so x-axis is not alphabetical
scale_x_discrete(limits=c("4-67/Chrimson","4-67/+","+/Chrimson", "+/+"))+
scale_fill_manual(values=c("#F99205", "#4ED55F", "#36A6D6", "#5752D0"))+
scale_color_manual(values=c("#F99205", "#4ED55F", "#36A6D6", "#5752D0"))+
geom_beeswarm(size = 1.5, alpha = .75, cex = 3)+
ylab("Percent Activity After Baseline Subtraction")+
theme_classic()+
theme(axis.title.x = element_blank(), axis.text.x = element_text(size = 16, color="black"), axis.ticks.x = element_blank())+
theme(axis.text.y = element_text(size = 24, color="black"), axis.ticks.y = element_blank())+
theme(axis.title.y = element_text (size = 24, color="black"))+
theme(axis.ticks.x = element_blank())+
theme(legend.position = "none")

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:

Making curved text on coord_polar

I want make curved text around ggplot with coord_polar. I have data.frame:
z <- data.frame( a=c("sensor 1","sensor 2","sensor 3","sensor 4","sensor 5","sensor 6","sensor 7","sensor 8"), b=c(50, 60, 70, 20,90,110,30,100))
And here is code where I create my ggplot:
cxc <- ggplot(z, aes(x=a, y=b, fill=factor(b))) +
geom_bar(width = 1,stat="identity",colour = "black")
cxc + coord_polar() +
theme_linedraw() +theme(axis.ticks =element_blank(), axis.text.y =element_blank(), axis.title=element_blank(), axis.text.x=element_text(size = 12,angle = 45))
Here is image from my result. I want making texts (x axis): sensor 1, sensor 2... making curved like I draw with red color around circle from coord_polar. Must fit with circle.
I am not sure on curving the text, but if you want them to at least rotate, this is a start:
myAng <-
seq(-20,-340,length.out = 8)
cxc + coord_polar() +
theme_linedraw() +
theme(axis.ticks =element_blank()
, axis.text.y =element_blank()
, axis.title=element_blank()
, axis.text.x=element_text(size = 12
,angle = myAng))
I will add in my hesitation on using such angles (or even polar coordinates for a plot like this). However, I assume that you have a good reason for doing it, and that this MWE just doesn't show it.
The {geomtextpath} package has a dedicated function for exactly this use case, including curved text. See also: here.
library(ggplot2)
library(geomtextpath) # remotes::install_github("AllanCameron/geomtextpath")
z <- data.frame(
a=c("sensor 1","sensor 2","sensor 3","sensor 4",
"sensor 5","sensor 6","sensor 7","sensor 8"),
b=c(50, 60, 70, 20,90,110,30,100)
)
cxc <- ggplot(z, aes(x=a, y=b, fill=factor(b))) +
geom_bar(width = 1,stat="identity",colour = "black")
cxc + coord_curvedpolar() +
theme_linedraw() +
theme(axis.ticks =element_blank(),
axis.text.y =element_blank(),
axis.title=element_blank(),
axis.text.x=element_text(size = 12))
Created on 2021-12-08 by the reprex package (v2.0.1)
Disclaimer: I'm a co-author of that package.
I don't know of a way to make them curve exactly like that using ggplot2 but we can at least remove the funny angle...
pm <- grid::unit(c(2, 2, 2, 2), "cm")
RadarTheme<-theme(panel.background=element_blank(),
plot.title= element_text(size = 25,face=c("bold","italic")),
plot.margin = pm,
text=element_text(family="Open Sans"), aspect.ratio = 1,
legend.position="bottom",legend.title=element_blank(),legend.direction="vertical",
strip.text.x = element_text(size = rel(0.8)),
axis.text.x = element_text(size = 15,face ="bold"),
axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
axis.line.x=element_line(size=0.5),
panel.grid.major=element_line(size=0.3,linetype = 2,colour="grey"))
cxc <- ggplot(z, aes(x=a, y=b, fill=factor(b))) +
geom_bar(width = 1,stat="identity",colour = "black")
cxc + coord_polar() + RadarTheme

drawing a box around a raster key

I'm plotting a species prediction map in ggplot using a spatial pixels data frame. I have the plot pretty much how I want it, the only problem is that my raster scale goes from white to red and so it's hard to see where it begins in the legend see the plot. I want to draw a box to outline to the legend key- just the bar going from white to red not the rest of it. I've being searching for over an hour but I can't find any way to do this, only ways to give the legend a background or draw a box around the legend text and bar, which I don't want to do. Does anyone know if this is possible to do in ggplot or do I need to change my colour gradient?
Thanks!
My plotting code:
ggplot() +
geom_raster(data=habs_pop_clip1, aes(x = easting.x, y = northing.x, fill = pred)) +
scale_fill_gradient("Probability of occurrence", low="white", high="red",limits = c(0,1)) +
coord_fixed(ratio=1, xlim=c(545000, 654000), ylim=c(278000,347000))+
geom_polygon(data=Norfolk1, aes(x=long, y=lat, Group=group), color="grey",fill=NA)+
theme(text = element_text(family = "serif")) +
geom_segment(aes(x = 550000, y = 278500, xend = 560000, yend = 278500), lineend = "round") +
annotate("text", x = 555000, xend = 555000, y = 282000, yend = 282000, label = "10 km", family = "serif", size = 4) +
ggtitle(colnames(bat_occ[i+7])) +
theme(plot.margin=unit(c(0.5, 0.5, 0.5, 0.5), "cm")) +
theme_bw() +
theme(axis.line = element_line(colour = "black"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.background = element_blank(),
axis.line=element_blank(),
axis.ticks=element_blank(),
axis.title.x=element_blank(),
axis.title.y=element_blank(),
axis.text =element_blank())
I don't know if there's a built-in parameter. If not, you could add a rectangle manually,
df <- reshape2::melt(outer(1:4, 1:4), varnames = c("X1", "X2"))
p <- ggplot(df, aes(X1, X2)) + geom_tile(aes(fill = value))+ scale_fill_continuous(guide = "colorbar")
g <- ggplotGrob(p)
g$grobs[[8]][[1]][[1]] <- gtable::gtable_add_grob(g$grobs[[8]][[1]][[1]],
rectGrob(gp=gpar(fill=NA, lwd=5)), 4, 2)
grid.newpage()
grid.draw(g)

Resources