Calculate average points in each bin of a shot chart with R - r

I'm trying to make a shot chart in which the color gradient represents the average of success in each bin.
The next script gives the count of each bin, How can I change it to represent average of success in each bin instead the count? I attach the script output chart.
#rm(list=ls())
data3<-read.csv("data10.csv",header=T)
require(jpeg)
require(grid)
court<-rasterGrob(readJPEG("nba_court.jpg"),
width=unit(1,"npc"), height=unit(1,"npc"))
require(hexbin)
require(ggplot2)
ggplot(data3, aes(x=loc_x, y=loc_y)) +
# annotation_custom(court, -247, 253, -50, 418) +
stat_binhex(bins = 18, colour = "gray", alpha = 0.8) +
scale_fill_gradientn(colours = c("cyan","yellow","red")) +
guides(alpha = FALSE, size = FALSE) +
xlim(250, -250) +
ylim(-52, 418) +
geom_rug(alpha = 0.5) +
coord_fixed() +
ggtitle("Kobe Bryant shots") +
theme(line = element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_blank(),
legend.title = element_blank(),
plot.title = element_text(size = 17, lineheight = 1.2, face = "bold"))
DATASET SAMPLE:
data3 <- data.frame(matrix(data=c(-98,-75,-119,83,10,-103,-191,69,196,-21,-106,-127,-180,50,125,200,34,45,99,120,108,184,102,206,113,-3,93,94,164,101,82,146,108,24,56,77,67,200,250,-45,1,0,0,0,1,1,0,0,0,0,1,1,0,1,0,1,1,0,0,1),
nrow=20,ncol=3))
colnames(data3)<-c("loc_x","loc_y","shot_made_flag")

You should use stat_summary_hex and set fun=mean in order to calculate the effectiveness inside each bin:
# Create random data
set.seed(1)
data3 = data.frame(loc_x = runif(1000,-250,250),
loc_y = rnorm(1000,230,50),
shot_made_flag = rbinom(1000,1,.5))
require(hexbin)
require(ggplot2)
# The first two lines have changed (z = shot_made_flag and using fun = mean)
ggplot(data3, aes(x=loc_x, y=loc_y, z = shot_made_flag)) +
stat_summary_hex(fun = mean, bins = 18, colour = "gray", alpha = 0.8) +
scale_fill_gradientn(colours = c("cyan","yellow","red")) +
guides(alpha = FALSE, size = FALSE) +
xlim(250, -250) +
ylim(-52, 418) +
geom_rug(alpha = 0.5) +
coord_fixed() +
ggtitle("Kobe Bryant shots") +
theme(line = element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_blank(),
legend.title = element_blank(),
plot.title = element_text(size = 17, lineheight = 1.2, face = "bold"))
Result:
Edited the full answer due to new data and to reflect the desired output (mean inside each hex cell)

Related

r adding line (new coordinates) to ggplot2 scaterplot

How can I add a line with new x coordinates to my scatterplot? I get an error saying the line x-values must match those from my scatterplot.. I tried using geom_line() as you can see
library(ggplot2)
x <- c(1,2,3)
y <- c(4,5,6)
a <- seq(0.5,5, by = 0.5)
b <- seq(1,10)
ggplot(as.data.frame(cbind(x,y)), aes(x, y)) +
geom_point(shape = 1) +
geom_point(aes(2.5,2.5, colour = "My Portfolio"),
shape = 18,
size = 3) +
geom_line(aes(a, b)) +
ggtitle("Efficient Frontier") +
xlab("Volatility (Weekly)") +
ylab("Expected Returns (Weekly)") +
theme(plot.title = element_text(size=14, face="bold.italic", hjust = 0.5, margin=margin(0,0,15,0)),
axis.title.x = element_text(size = 10, margin=margin(15,0,0,0)),
axis.title.y = element_text(size = 10, margin=margin(0,15,0,0)),
panel.border = element_rect(colour = "black", fill=NA, size=1),
legend.position = c(0.93,0.06),
legend.title = element_blank(),
legend.text = element_text(size=8),
legend.background = element_rect(color = "black"),
legend.key=element_blank())
thanks!
You have to provide a new data.frame to geom_line() and set the aestetics accordingly.
library(ggplot2)
x <- c(1,2,3); y <- c(4,5,6)
a <- seq(0.5,5, by = 0.5); b <- seq(1,10)
ggplot(as.data.frame(cbind(x,y)), aes(x, y)) +
geom_point(shape = 1) +
geom_point(aes(2.5,2.5, colour = "My Portfolio"),
shape = 18,
size = 3) +
geom_line(data=data.frame(a,b), mapping=aes(x=a, y=b)) +
ggtitle("Efficient Frontier") +
xlab("Volatility (Weekly)") +
ylab("Expected Returns (Weekly)") +
theme(plot.title = element_text(size=14, face="bold.italic", hjust = 0.5, margin=margin(0,0,15,0)),
axis.title.x = element_text(size = 10, margin=margin(15,0,0,0)),
axis.title.y = element_text(size = 10, margin=margin(0,15,0,0)),
panel.border = element_rect(colour = "black", fill=NA, size=1),
legend.position = c(0.93,0.06),
legend.title = element_blank(),
legend.text = element_text(size=8),
legend.background = element_rect(color = "black"),
legend.key=element_blank())

R - How to add percentages to ggplot2 pie chart legend?

I would like to add percentages (rounded to 1 decimal) to my legend.
For example, "MSFT 8.3%".
I don't want them in the pie chart since it looks weird when theres too many slices with small % values.
Here is my code:
library(ggplot2)
tickers <- c("msft","xic.to","fb","aapl","goog","nflx","aal","bmo","xef.to","xec.to","vsp.to","mcd")
Weights <- rep(1/12*100,12)
tickers <- tickers[order(Weights)]; Weights <- sort(Weights)
tickers.factor <- factor(tickers, levels = as.character(tickers))
ypos <- cumsum(Weights) - 0.5*Weights
ypos <- 100 - ypos
ggplot() + theme_bw() +
geom_bar(aes(x = "", y = Weights, fill = tickers.factor),
stat = "identity", color = "white") +
coord_polar("y", start = 0) +
ggtitle("Portfolio Weights") +
theme(plot.title = element_text(hjust = 0.5, size = 20),
axis.title = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
panel.grid = element_blank(),
panel.border = element_blank()) +
guides(fill = guide_legend(reverse = TRUE)) +
#scale_fill_brewer(palette = "PiYG", name = "Tickers") +
theme(legend.text = element_text(size = 12),
legend.title = element_text(hjust = 0.5, size = 15),
legend.key.size = unit(0.8,"cm"))
Thank you
I've used scales::percent to format the percentages.
library(ggplot2)
tickers <- c("msft","xic.to","fb","aapl","goog","nflx","aal","bmo","xef.to","xec.to","vsp.to","mcd")
Weights <- rmultinom(n = 1, size = 100, prob = rep(1/length(tickers), length(tickers)))
tickers <- tickers[order(Weights)]; Weights <- sort(Weights)
Percent <- factor(paste(tickers, scales::percent(Weights/100, accuracy = 0.01)), paste(tickers, scales::percent(Weights/100, accuracy = 0.01)))
ypos <- cumsum(Weights) - 0.5*Weights
ypos <- 100 - ypos
ggplot() + theme_bw() +
geom_bar(aes(x = "", y = Weights, fill = Percent),
stat = "identity", color = "white") +
coord_polar("y", start = 0) +
ggtitle("Portfolio Weights") +
theme(plot.title = element_text(hjust = 0.5, size = 20),
axis.title = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
panel.grid = element_blank(),
panel.border = element_blank()) +
guides(fill = guide_legend(reverse = TRUE)) +
#scale_fill_brewer(palette = "PiYG", name = "Tickers") +
theme(legend.text = element_text(size = 12),
legend.title = element_text(hjust = 0.5, size = 15),
legend.key.size = unit(0.8,"cm"))

plotting p-values using ggplot stat_summary

I want to plot a dataframe (stats) with the coefficient and error bars, and automatically write the p-values above each point.
stats <- data.frame(Coefficient = c(-0.07,-0.04,-0.15173266),
p_value = c(.0765210755,0.5176050652,0.0001309025),
conf_low = c(-.1544418,-0.1686583,-0.2294873),
conf_high = c(0.007812205,0.084939487,-0.073978033),
Test = c("TestA","TestB","TestC"))
I am trying to make a function to plot the p-values above each Coefficient point. (The coord_flip in the plot below may also be throwing me off.
give.pval <- function(y){
return(c(x = Coefficient, label = stats$p_value))
}
The following ggplot is exactly what I need, except for the stat_summary line which I am doing incorrectly
ggplot(stats, aes(x = Test, y = Coefficient)) +
geom_point(aes(size = 6)) +
geom_errorbar(aes(ymax = conf_high, ymin = conf_low)) +
geom_hline(yintercept=0, linetype="dashed") +
#stat_summary(fun.data = give.pval, geom = "text") +
theme_calc() +
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
axis.text.x = element_text(size = 12, vjust = 0.5), axis.title.x = element_text(size = 16),
axis.text.y = element_text(size = 12), axis.title.y = element_blank(),
legend.position = "none",
plot.title = element_text(hjust = 0.5, size = 24)) +
coord_flip() +
ylab("Coefficient")
I would like the have this plot but with the appropriate p-value above each of the three Coefficient points.
Thanks for any advice.
This could be achieved with a geom_text layer where you map p_value on the label aes and some additional nudging
library(ggplot2)
stats <- data.frame(Coefficient = c(-0.07,-0.04,-0.15173266),
p_value = c(.0765210755,0.5176050652,0.0001309025),
conf_low = c(-.1544418,-0.1686583,-0.2294873),
conf_high = c(0.007812205,0.084939487,-0.073978033),
Test = c("TestA","TestB","TestC"))
ggplot(stats, aes(x = Test, y = Coefficient)) +
geom_point(aes(size = 6)) +
geom_errorbar(aes(ymax = conf_high, ymin = conf_low)) +
geom_hline(yintercept=0, linetype="dashed") +
geom_text(aes(label = p_value), nudge_x = .2) +
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
axis.text.x = element_text(size = 12, vjust = 0.5), axis.title.x = element_text(size = 16),
axis.text.y = element_text(size = 12), axis.title.y = element_blank(),
legend.position = "none",
plot.title = element_text(hjust = 0.5, size = 24)) +
coord_flip() +
ylab("Coefficient")

Modify the size of a pie chart with ggplot in R

I have run the following ggplot function :
g <- ggplot(results_table, aes(x = "", y = Pct*100, fill = Criteria),width = 0.5) +
geom_bar(stat = "identity", color = Palcolor, fill = Palcolor) +
coord_polar(theta = "y", start = 0, direction = -1) +
theme_minimal() +
theme(legend.position = "none", axis.title.x = element_blank(), axis.title.y = element_blank(),
panel.border = element_blank(), panel.grid = element_blank(), axis.text = element_blank(),
axis.ticks = element_blank(), legend.title = element_blank(),
plot.title = element_text(size = 14, hjust = 0.5, vjust = 0)) +
geom_text(aes(label = paste0(Criteria,"; ",sprintf("%0.1f", round(Pct*100, digits = 1)),"%")),
position = position_stack (vjust = 0.5, reverse = TRUE)) +
labs(title = gTitle)
}
and the pie is the following :
but it is too large. I would like to have a diameter smaller than the length of the second part of the title. How can I proceed ?

Add legend to ggplot object (why two legends?)

I created a ggplot2 object:
a <- replicate(8,rnorm(100))
colnames(a) <- letters[1:8]
b < -melt(a,id.vars=1:1)
colnames(b) <- c("c","variable","value")
ggplot(b,aes(x = c,y = value, colour = variable, linetype = variable)) +
geom_line()+
geom_point(aes(shape = factor(variable)), size = 1.7) +
scale_x_continuous(limits = c(-1, 1),
breaks = seq(-1, 1, 0.1),
expand=c(0.01, 0.01)) +
scale_y_continuous(limits = c(-1, 1),
breaks = seq(-1, 1, 0.1),
expand = c(0.01, 0.01))+
theme_bw(base_size = 12, base_family = "Helvetica") +
theme(axis.text=element_text(size = 10),
axis.title=element_text(size = 10),
text = element_text(size = 10),
axis.line = element_line(size = 0.25),
axis.ticks=element_line(size = 0.25),
panel.grid.major = element_blank(),
#panel.grid.minor = element_blank(),
panel.border = element_rect(colour = "black", fill = NA, size = 0.5),
panel.background = element_blank(),
legend.position = "top" ,
legend.direction = "vertical",
legend.title = element_blank(),
legend.text = element_text(size = 13),
legend.background = element_blank(),
legend.key = element_blank()) +
labs(x = '', y = '', title = "") +
theme(plot.title = element_text(size=10)) +
theme(strip.text.x = element_text(size = 8,color="black"),
strip.background = element_blank()) +
theme(strip.text.x = element_text(size = 8, colour = "black"))
My problem is the following:
when I create the legend, there is a separate legend for the colors and a separate one for the points.
How can I create a single legend for each of the 8 variables?
Let me minimise your code and focus on the legend issue. This is what you have now.
ggplot(b,aes(x = c, y = value, colour = variable, linetype = variable)) +
geom_line() +
geom_point(aes(shape = factor(variable)),size=1.7)
Your data frame, b has variable as factor. You use this in two ways here; variable and factor(variable). You can simply use variable for shape in geom_point; make all variable identical.
ggplot(b,aes(x = c, y = value, colour = variable, linetype = variable)) +
geom_line()+
geom_point(aes(shape = variable),size = 1.7)
I saw some warning messages related to colours and other things. You may want to take care of them. But, for legend, this is one way to go.
Take from the ideas on this page: http://www.cookbook-r.com/Graphs/Legends_(ggplot2)/#modifying-the-text-of-legend-titles-and-labels
I edited your code to make the data visible (you had problems with your x-axis limits. Note the final three lines. These commands tell ggplot to create only one legend.
a<-replicate(6,rnorm(100))
colnames(a)<-letters[1:6]
b<-melt(a,id.vars=1:1)
colnames(b)<-c("c","variable","value")
ggplot(b,aes(x=c,y=value,colour=variable,linetype=variable)) +
geom_line() + geom_point(aes(shape=factor(variable)),size=1.7)+
scale_x_continuous(limits=c(0,100))+
scale_y_continuous(limits=c(-2,2),breaks=seq(-2,2,0.1),expand=c(0.01,0.01))+
theme_bw(base_size=12, base_family="Helvetica") +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=10),
text = element_text(size=10),
axis.line = element_line(size=0.25),
axis.ticks=element_line(size=0.25),
panel.grid.major = element_blank(),
#panel.grid.minor = element_blank(),
panel.border = element_rect(colour="black",fill=NA,size=0.5),
panel.background = element_blank(),
legend.position="top" ,
legend.direction="vertical",
legend.title=element_blank(),
legend.text=element_text(size=13),
legend.background=element_blank(),
legend.key=element_blank())+
labs(x='', y='',title="")+
theme(plot.title=element_text(size=10))+
theme(strip.text.x = element_text(size = 8,color="black"),strip.background=element_blank())+
theme(strip.text.x = element_text(size = 8,color="black"))+
scale_colour_discrete(name ="Factor")+
scale_linetype_discrete(name ="Factor") +
scale_shape_discrete(name ="Factor")

Resources