I need a flexible way to make radar / spider charts in ggplot2. From solutions I've found on github and the ggplot2 group, I've come this far:
library(ggplot2)
# Define a new coordinate system
coord_radar <- function(...) {
structure(coord_polar(...), class = c("radar", "polar", "coord"))
}
is.linear.radar <- function(coord) TRUE
# rescale all variables to lie between 0 and 1
scaled <- as.data.frame(lapply(mtcars, ggplot2:::rescale01))
scaled$model <- rownames(mtcars) # add model names as a variable
as.data.frame(melt(scaled,id.vars="model")) -> mtcarsm
ggplot(mtcarsm, aes(x = variable, y = value)) +
geom_path(aes(group = model)) +
coord_radar() + facet_wrap(~ model,ncol=4) +
theme(strip.text.x = element_text(size = rel(0.8)),
axis.text.x = element_text(size = rel(0.8)))
which works, except for the fact that lines are not closed.
I thougth that I would be able to do this:
mtcarsm <- rbind(mtcarsm,subset(mtcarsm,variable == names(scaled)[1]))
ggplot(mtcarsm, aes(x = variable, y = value)) +
geom_path(aes(group = model)) +
coord_radar() + facet_wrap(~ model,ncol=4) +
theme(strip.text.x = element_text(size = rel(0.8)),
axis.text.x = element_text(size = rel(0.8)))
in order to join the lines, but this does not work. Neither does this:
closes <- subset(mtcarsm,variable == names(scaled)[c(1,11)])
ggplot(mtcarsm, aes(x = variable, y = value)) +
geom_path(aes(group = model)) +
coord_radar() + facet_wrap(~ model,ncol=4) +
theme(strip.text.x = element_text(size = rel(0.8)),
axis.text.x = element_text(size = rel(0.8))) + geom_path(data=closes)
which does not solve the problem, and also produces lots of
"geom_path: Each group consist of only one observation. Do you need to
adjust the group aesthetic?"
messages. Som, how do I go about closing the lines?
/Fredrik
Using the new ggproto mechanism available in ggplot2 2.0.0, coord_radar can be defined as:
coord_radar <- function (theta = "x", start = 0, direction = 1)
{
theta <- match.arg(theta, c("x", "y"))
r <- if (theta == "x")
"y"
else "x"
ggproto("CoordRadar", CoordPolar, theta = theta, r = r, start = start,
direction = sign(direction),
is_linear = function(coord) TRUE)
}
Not sure if the syntax is perfect but it is working...
The codes here seem outdated for ggplot2: 2.0.0
Try my package zmisc: devtools:install_github("jerryzhujian9/ezmisc")
After you install it, you will be able to run:
df = mtcars
df$model = rownames(mtcars)
ez.radarmap(df, "model", stats="mean", lwd=1, angle=0, fontsize=0.6, facet=T, facetfontsize=1, color=id, linetype=NULL)
ez.radarmap(df, "model", stats="none", lwd=1, angle=0, fontsize=1.5, facet=F, facetfontsize=1, color=id, linetype=NULL)
if you are curious about what's inside, see my codes at github:
The main codes were adapted from http://www.cmap.polytechnique.fr/~lepennec/R/Radar/RadarAndParallelPlots.html
solution key factor
add duplicated mpg row after melt by rbind
inherit CoordPolar on ggproto
set is_linear = function() TRUE on ggproto
especially is_linear = function() TRUE is important,
since if not you will get plot like this...
with is_linear = function() TRUE settings you can get,
library(dplyr)
library(data.table)
library(ggplot2)
rm(list=ls())
scale_zero_to_one <-
function(x) {
r <- range(x, na.rm = TRUE)
min <- r[1]
max <- r[2]
(x - min) / (max - min)
}
scaled.data <-
mtcars %>%
lapply(scale_zero_to_one) %>%
as.data.frame %>%
mutate(car.name=rownames(mtcars))
plot.data <-
scaled.data %>%
melt(id.vars='car.name') %>%
rbind(subset(., variable == names(scaled.data)[1]))
# create new coord : inherit coord_polar
coord_radar <-
function(theta='x', start=0, direction=1){
# input parameter sanity check
match.arg(theta, c('x','y'))
ggproto(
NULL, CoordPolar,
theta=theta, r=ifelse(theta=='x','y','x'),
start=start, direction=sign(direction),
is_linear=function() TRUE)
}
plot.data %>%
ggplot(aes(x=variable, y=value, group=car.name, colour=car.name)) +
geom_path() +
geom_point(size=rel(0.9)) +
coord_radar() +
facet_wrap(~ car.name, nrow=4) +
theme_bw() +
theme(
axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.x = element_blank(),
legend.position = 'none') +
labs(title = "Cars' Status")
final result
Sorry, I was beeing stupid. This seems to work:
library(ggplot2)
# Define a new coordinate system
coord_radar <- function(...) {
structure(coord_polar(...), class = c("radar", "polar", "coord"))
}
is.linear.radar <- function(coord) TRUE
# rescale all variables to lie between 0 and 1
scaled <- as.data.frame(lapply(mtcars, ggplot2:::rescale01))
scaled$model <- rownames(mtcars) # add model names as a variable
as.data.frame(melt(scaled,id.vars="model")) -> mtcarsm
mtcarsm <- rbind(mtcarsm,subset(mtcarsm,variable == names(scaled)[1]))
ggplot(mtcarsm, aes(x = variable, y = value)) +
geom_path(aes(group = model)) +
coord_radar() + facet_wrap(~ model,ncol=4) +
theme(strip.text.x = element_text(size = rel(0.8)),
axis.text.x = element_text(size = rel(0.8)))
It turns out than geom_polygom still produces a polygon in the polar coordinates so that
# rescale all variables to lie between 0 and 1
scaled <- as.data.frame(lapply(mtcars, ggplot2:::rescale01))
scaled$model <- rownames(mtcars) # add model names as a variable
# melt the dataframe
mtcarsm <- reshape2::melt(scaled)
# plot it as using the polygon geometry in the polar coordinates
ggplot(mtcarsm, aes(x = variable, y = value)) +
geom_polygon(aes(group = model), color = "black", fill = NA, size = 1) +
coord_polar() + facet_wrap( ~ model) +
theme(strip.text.x = element_text(size = rel(0.8)),
axis.text.x = element_text(size = rel(0.8)),
axis.ticks.y = element_blank(),
axis.text.y = element_blank()) +
xlab("") + ylab("")
works perfectly...
Thank you guys for the help but it did not cover all of my needs. I used two series of data to be compared so I took the subset of mtcars for Mazda:
nobody mentioned about order of the x variable and ggplot2 sorts this variable for the plot but does not sort the data and it made my chart wrong at the first attempt. Apply sorting function for me it was dplyr::arrange(plot.data, x.variable.name)
I needed to annotate the chart with values and ggplot2::annotate() works fine but it was not included in the recent answers
the above code did not work fine for my data until adding ggplot2::geom_line
Finally this code chunk did my chart:
scaled <- as.data.frame(lapply(mtcars, ggplot2:::rescale01))
scaled$model <- rownames(mtcars)
mtcarsm <- scaled %>%
filter(grepl('Mazda', model)) %>%
gather(variable, value, mpg:carb) %>%
arrange(variable)
ggplot(mtcarsm, aes(x = variable, y = value)) +
geom_polygon(aes(group = model, color = model), fill = NA, size = 1) +
geom_line(aes(group = model, color = model), size = 1) +
annotate("text", x = mtcarsm$variable, y = (mtcarsm$value + 0.05), label = round(mtcarsm$value, 2), size = 3) +
theme(strip.text.x = element_text(size = rel(0.8)),
axis.text.x = element_text(size = rel(1.2)),
axis.ticks.y = element_blank(),
axis.text.y = element_blank()) +
xlab("") + ylab("") +
guides(color = guide_legend()) +
coord_radar()
Hopefully usefull for somebody
Related
I am doing a scatterplot with a facet_grid() like that:
library(ggplot2)
ggplot(df, aes(x, y)) +
geom_point() +
facet_grid(group1 ~ group2)
I want the y axis title y to be in the middle of each row like this (paint solution):
The numbers of facet rows is two in this example because df$group2 has two different values. For my actual use case there may be more than two rows depending on the used facet variable; the y axis title is supposed to be in the middle of each facet row.
Best solution so far is adding spaces which is a mess since using y axis titles of different length shifts the text away from the middle of the rows. It must be with ggplot2, i.e. without the usage of additional packages. I make a package and do not want to rely on/ include too many packages.
Data used here:
df <- data.frame(x= rnorm(100), y= rnorm(100),
group1= rep(0:1, 50), group2= rep(2:3, each= 50))
Without using another package, I felt that the best method would be to build upon the spaces solution you linked in the original question. So I wrote a function to make the label spacing a little bit more robust.
ylabel <- function(label1,label2){
L1 <- nchar(label1)
L2 <- nchar(label2)
scaler <- ifelse(L1 + L2 > 8, 4, 0)
space1 = paste0(rep("",27 - (L1/2)),collapse = " ")
space2 = paste0(rep("",44 - (L1/2 + L2/2) - scaler), collapse = " ")
space3 = paste0(rep("",22 - (L2/2)), collapse = " ")
paste0(space1,label1,space2,label2,space3)
}
Application:
test <- ylabel("automobiles", "trucks")
ggplot(df, aes(x, y)) +
geom_point() +
facet_grid(group1 ~ group2) +
ylab(test)
Still playing around with the scaler parameter, it's not perfect:
test2 <- ylabel("super long label", "a")
ggplot(df, aes(x, y)) +
geom_point() +
facet_grid(group1 ~ group2) +
ylab(test2)
Will continue to refine the function/parameters, but am thinking this will get you close to what you're looking for.
You can copy the axis labels into new grobs in the gtable. Note that although this uses the grid and gtable packages, these are already imported by ggplot2, so this does not add any new dependencies that are not already available and used internally by ggplot.
library(grid)
library(gtable)
g = ggplot(df, aes(x, y)) +
geom_point() +
facet_grid(group1 ~ group2)
gt = ggplot_gtable(ggplot_build(g))
which.ylab = grep('ylab-l', gt$layout$name)
gt = gtable_add_grob(gt, gt$grobs[which.ylab], 8, 3)
gt = gtable_add_grob(gt, gt$grobs[which.ylab], 10, 3)
gt = gtable_filter(gt, 'ylab-l', invert = TRUE) # remove the original axis title
grid.draw(gt)
The above works for OP's example with just two facets. If we want to generalise this for an arbitrary number of facets we can do that simply enough by searching the gtable to see which rows contain y-axes.
gt = ggplot_gtable(ggplot_build(g))
which.ylab = grep('ylab-l', gt$layout$name)
which.axes = grep('axis-l', gt$layout$name)
axis.rows = gt$layout$t[which.axes]
label.col = gt$layout$l[which.ylab]
gt = gtable::gtable_add_grob(gt, rep(gt$grobs[which.ylab], length(axis.rows)), axis.rows, label.col)
gt = gtable::gtable_filter (gt, 'ylab-l', invert = TRUE)
grid::grid.draw(gt)
In the version above, I also use :: to explicitly specify the namespace for the functions from the grid and gtable packages. This will allow the code to work without even loading the additional packages into the search path.
Demonstrating this code with another example with four facet rows:
df <- data.frame(x= rnorm(100), y= rnorm(100),
group1= rep(1:4, 25), group2= rep(1:2, each= 50))
You may consider switching to library(cowplot) for more control
The following code could be added to a function, but I left it long for clarity. Create 4 dataframes and feed them to four plots. Then arrange the plots
library(tidyverse)
df <- data.frame(x= rnorm(100), y= rnorm(100),
group1= rep(0:1, 50), group2= rep(2:3, each= 50))
library(cowplot)
df1 <- df %>%
filter(group2 == 2) %>%
filter(group1 == 0)
df2 <- df %>%
filter(group2 == 3) %>%
filter(group1 == 0)
df3 <- df %>%
filter(group2 == 2) %>%
filter(group1 == 1)
df4 <- df %>%
filter(group2 == 3) %>%
filter(group1 == 1)
plot1 <- ggplot(df1, aes(x, y)) +
geom_point() +
facet_grid(group1 ~ group2)+
xlim(c(-3, 3))+
ylim(c(-3, 2))+
theme(strip.text.y = element_blank(),
axis.title.x = element_blank(),
axis.text.x = element_blank(),
axis.ticks.x = element_blank()
)
plot1
plot2 <- ggplot(df2, aes(x, y)) +
geom_point() +
facet_grid(group1 ~ group2)+
xlim(c(-3, 3))+
ylim(c(-3, 2))+
theme(axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.x = element_blank(),
axis.text.x = element_blank(),
axis.ticks.x = element_blank()
)
plot2
plot3 <- ggplot(df3, aes(x, y)) +
geom_point() +
facet_grid(group1 ~ group2)+
xlim(c(-3, 3))+
ylim(c(-3, 2))+
theme(strip.text.x = element_blank(),
strip.text.y = element_blank())
plot3
plot4 <- ggplot(df4, aes(x, y)) +
geom_point() +
facet_grid(group1 ~ group2)+
xlim(c(-3, 3))+
ylim(c(-3, 2))+
theme(axis.title.y = element_blank(),
strip.text.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank())
plot4
plot_grid(plot1, plot2, plot3, plot4)
Here is a version with annotation, using ggplot2 only. It should be scalable.
No messing with grobs. The disadvantage is that the x positioning and the plot margins need to be semi-manually defined and this might not be very robust.
library(ggplot2)
df <- data.frame(x= rnorm(100), y= rnorm(100),
group1= rep(0:1, 50), group2= rep(2:3, each= 50))
## define a new data frame based on your groups, so this is scalable
annotate_ylab <- function(df, x, y, group1, group2, label = "label") {
## make group2 a factor, so you know which column will be to the left
df[[group2]] <- factor(df[[group2]])
lab_df <- data.frame(
## x positioning is a bit tricky,
## I think a moderately robust method is to
## set it relativ to the range of your values
x = min(df[[x]]) - 0.2 * diff(range(df[[x]])),
y = mean(df[[y]]),
g1 = unique(df[[group1]]),
## draw only on the left column
g2 = levels(df[[group2]])[1],
label = label
)
names(lab_df) <- c(x, y, group1, group2, "label")
lab_df
}
y_df <- annotate_ylab(df, "x", "y", "group1", "group2", "y")
ggplot(df, aes(x, y)) +
geom_point() +
geom_text(data = y_df, aes(x, y, label = label), angle = 90) +
facet_grid(group1 ~ group2) +
coord_cartesian(xlim = range(df$x), clip = "off") +
theme(axis.title.y = element_blank(),
plot.margin = margin(5, 5, 5, 20))
y_df_mtcars <- annotate_ylab(mtcars, "mpg", "disp", "carb", "vs", "y")
ggplot(mtcars, aes(mpg, disp)) +
geom_point() +
geom_text(data = y_df_mtcars, aes(mpg, disp, label = label), angle = 90) +
facet_grid(carb ~ vs) +
coord_cartesian(xlim = range(mtcars$mpg), clip = "off") +
theme(axis.title.y = element_blank(),
plot.margin = margin(5, 5, 5, 20))
Created on 2021-11-24 by the reprex package (v2.0.1)
By using ggplot and faced_grid functions I'm trying to make a heatmap. I have a categorical y axis, and I want y axis labels to be left aligned. When I use theme(axis.text.y.left = element_text(hjust = 0)), each panels' labels are aligned independently. Here is the code:
#data
set.seed(1)
gruplar <- NA
for(i in 1:20) gruplar[i] <- paste(LETTERS[sample(c(1:20),sample(c(1:20),1),replace = T) ],
sep="",collapse = "")
gruplar <- cbind(gruplar,anagruplar=rep(1:4,each=5))
tarih <- data.frame(yil= rep(2014:2019,each=12) ,ay =rep_len(1:12, length.out = 72))
gruplar <- gruplar[rep(1:nrow(gruplar),each=nrow(tarih)),]
tarih <- tarih[rep_len(1:nrow(tarih),length.out = nrow(gruplar)),]
grouped <- cbind(tarih,gruplar)
grouped$value <- rnorm(nrow(grouped))
#plot
p <- ggplot(grouped,aes(ay,gruplar,fill=value))
p <- p + facet_grid(anagruplar~yil,scales = "free",
space = "free",switch = "y")
p <- p + theme_minimal(base_size = 14) +labs(x="",y="") +
theme(strip.placement = "outside",
strip.text.y = element_text(angle = 90))
p <- p + geom_raster(aes(fill = value), na.rm = T)
p + theme(axis.text.y.left = element_text(hjust = 0, size=14))
I know that by putting spaces and using a mono-space font I can solve the problem, but I have to use the font 'Calibri Light'.
Digging into grobs isn't my favourite hack, but it can serve its purpose here:
# generate plot
# (I used a smaller base_size because my computer screen is small)
p <- ggplot(grouped,aes(ay,gruplar,fill=value)) +
geom_raster(aes(fill = value),na.rm = T) +
facet_grid(anagruplar~yil,scales = "free",space = "free",switch = "y") +
labs(x="", y="") +
theme_minimal(base_size = 10) +
theme(strip.placement = "outside",
strip.text.y = element_text(angle = 90),
axis.text.y.left = element_text(hjust = 0, size=10))
# examine ggplot object: alignment is off
p
# convert to grob object: alignment is unchanged (i.e. still off)
gp <- ggplotGrob(p)
dev.off(); grid::grid.draw(gp)
# change viewport parameters for left axis grobs
for(i in which(grepl("axis-l", gp$layout$name))){
gp$grobs[[i]]$vp$x <- unit(0, "npc") # originally 1npc
gp$grobs[[i]]$vp$valid.just <- c(0, 0.5) # originally c(1, 0.5)
}
# re-examine grob object: alignment has been corrected
dev.off(); grid::grid.draw(gp)
I guess one option is to draw the labels on the right-hand side, and move that column in the gtable,
p <-ggplot(grouped,aes(ay,gruplar,fill=value)) +
facet_grid(anagruplar~yil,scales = "free",space = "free",switch = "y") +
geom_raster(aes(fill = value),na.rm = T) +
theme_minimal(base_size = 12) + labs(x="",y="") +
scale_y_discrete(position='right') +
theme(strip.placement = "outside", strip.text.y = element_text(angle = 90))+
theme(axis.text.y.left = element_text(hjust = 0,size=14))
g <- ggplotGrob(p)
id1 <- unique(g$layout[grepl("axis-l", g$layout$name),"l"])
id2 <- unique(g$layout[grepl("axis-r", g$layout$name),"l"])
g2 <- gridExtra::gtable_cbind(g[,seq(1,id1-1)],g[,id2], g[,seq(id1+1, id2-1)], g[,seq(id2+1, ncol(g))])
library(grid)
grid.newpage()
grid.draw(g2)
This seems like a bug in ggplot2, or at least what I consider an undesirable / unexpected behavior. You may have seen the approach suggested here, which uses string padding on a mono-space font to achieve the alignment.
This is pretty hacky, but if you need to achieve alignment using a particular font, you might replace the axis labels altogether with geom_text. I have a mostly-working solution, but it is ugly, in that each step seems to break something else!
library(ggplot2); library(dplyr)
# To add a blank facet before 2014, I convert to character
grouped$yil = as.character(grouped$yil)
# I add some rows for the dummy facet, in year "", to use for labels
grouped <- grouped %>%
bind_rows(grouped %>%
group_by(gruplar) %>%
slice(1) %>%
mutate(yil = "",
value = NA_real_) %>%
ungroup())
p <- ggplot(grouped,
aes(ay,gruplar,fill=value)) +
geom_raster(aes(fill = value),na.rm = T) +
scale_x_continuous(breaks = 4*0:3) +
facet_grid(anagruplar~yil,
scales = "free",space = "free",switch = "y") +
theme_minimal(base_size = 14) +
labs(x="",y="") +
theme(strip.placement = "outside",
strip.text.y = element_text(angle = 90),
axis.text.y.left = element_blank(),
panel.grid = element_blank()) +
geom_text(data = grouped %>%
filter(yil == ""),
aes(x = -40, y = gruplar, label = gruplar), hjust = 0) +
scale_fill_continuous(na.value = "white")
p
(The last problem with this plot that I can see is that it shows an orphaned "0" on the x axis of the dummy facet. Need another hack to get rid of that!)
All I want is this R code to display the names of players inside the "topName" while hiding the names inside the "otherNames" by plotting both of them using two different geom_col().
epldata <- read.csv(file = 'epldata.csv')
epldata$srno <- c(1:461)
attach(epldata)
points <- epldata[order(-fpl_points),]
detach(epldata)
topNames[24:461]<-NA epldata$topNames <- topNames
topPoints[24:461]<-NA epldata$topPoints <- topPoints
epldata$otherNames <- NA epldata$otherNames[24:461] <-
as.character(points$name[c(24:461)]) epldata$otherPoints <- NA
epldata$otherPoints[24:461] <-
as.numeric(points$fpl_points[c(24:461)])
ggplot(data = epldata)+ geom_col(aes(x=epldata$topNames,
y=epldata$topPoints), fill = "red", alpha = 1) +
theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
annotate("text", x=epldata$topNames, y=-50, #epldata$topPoints,
label = epldata$topNames, fontface = 1, size = 2, hjust = 0)+ geom_col(aes(x=epldata$otherNames, y=epldata$otherPoints), fill
= "gray", alpha = 0.3)+ theme(legend.position = "none")+ #theme(axis.text.x = element_text(angle = 90, hjust = 1))+ xlab("Player Names")+ ylab("FPL Points")+ guides(fill=FALSE,
color=FALSE, guide = FALSE) + coord_flip() + theme(axis.text.y =
element_blank(),
axis.ticks.y = element_blank())
This is the kind of output I am looking for but without using the Annotate Hack that I am currently using but directly plotting the names on the axis.
Update : have added the entire code and the link to the data set is below :
https://drive.google.com/open?id=1KTitWDcLIBmeBsz8mLcHXDIyhQLZnlhS
Once you've created a list of topNames, you can use scale_x_continuous to display only these axis labels:
scale_x_discrete(breaks = topNames)
Also, rather than using two separate geom_col() geometries, you can create a new "highlight" column in the dataframe and use that with the fill and alpha aesthetics:
library(dplyr)
library(ggplot2)
# read data from google drive
id <- "1KTitWDcLIBmeBsz8mLcHXDIyhQLZnlhS" #google file ID
epldata <- read.csv(sprintf("https://docs.google.com/uc?id=%s&export=download", id),
stringsAsFactors = FALSE)
N <- 24 #number of players to highlight
#get list of names of top N players
topNames <- epldata %>%
arrange(-fpl_points) %>%
head(N) %>%
pull(name)
#> Warning: package 'bindrcpp' was built under R version 3.5.1
# make variable for highlighting
epldata <- epldata %>%
mutate(highlight = ifelse(name %in% topNames, TRUE, FALSE))
ggplot(data = epldata,
aes(x = name, y = fpl_points, fill = highlight, alpha = highlight)) +
geom_col() +
scale_fill_manual(guide = FALSE,
values = c("gray", "red")) +
scale_alpha_manual(guide = FALSE,
values = c(0.4, 1)) +
scale_x_discrete(breaks = topNames) + #use breaks to determine axis labels
coord_flip() +
ylab("FPL Points") +
theme_classic() +
theme(axis.ticks.y = element_blank(),
axis.title.y = element_blank())
Created on 2018-09-19 by the reprex package (v0.2.1)
I'm having trouble with the sizing and aligning of one my plots using the plot_grid function in the cowplot package. The bottom left plot always seems to be a tad bit smaller then the others. I did some researching and couldn't seem to find anything that works. I'm new to R, so any help would be greatly appreciated! Thanks!
Attached is my code as well as what the plot is looking like and what I want it to look like
'#Data frame with huc results for each parameter
parameter_results <- readRDS("param_results_2014.RDS") %>% select(1:84)
#list of parameter names
parameters <- sort(readRDS("parameters.RDS"))
blank_theme <- theme_minimal()+ theme(
axis.title.x = element_blank(),
plot.margin = unit(c(0,0,0,0), "pt"),
axis.title.y = element_blank(),
panel.border = element_blank(),
legend.position=c(.5,.02),
legend.direction="horizontal",
legend.key=element_rect(colour="black",size=0.5,linetype="solid"),
panel.grid=element_blank(),
axis.ticks = element_blank(),
plot.title= element_text(size=8, vjust=-4.0, face="bold")
)
#Function for creating poroportions table for parameters
parameter_summary <-function(parameter) {
parameter_df <- parameter_results %>%
select(results = parameter) %>% #keep only column for the parameter you want to plot
filter(results != "Not Applicable") %>% #filters out 'not applicable' results
count(results) %>% #
mutate(prop = prop.table(n), perc = paste0(round(prop * 100),"%"))
return(parameter_df)
}
parameter_pie_chart <- function(parameter,title="",nudgex=5,nudgey=-10) {
# parameter: the parameter you want to create a pie chart for, example: 'DO'
# title: plot title, default is the name of the parameter
parameter_df <- parameter_summary(parameter)
#data frame of proportions less than 10%. necessary because for these values, labels are implemented with an arrow
small_perc <- parameter_df %>% filter(prop < .10)
#dataframe of proportions greater than 10%
signif_perc <- parameter_df %>% filter(prop >= .10)
pie_chart <- ggplot(parameter_df, aes(x = "", y = n, fill = fct_inorder(results))) +
geom_bar(stat = "identity", width = 1,colour='black') +
coord_polar(theta = "y") +
blank_theme +
theme(axis.text.x=element_blank()) +
theme(legend.title=element_blank()) +
#ggtitle(title)+
theme(plot.title = element_text(hjust = 0.5)) +
geom_text(data = signif_perc, aes(label = perc),
position = position_stack(vjust = .5), size = 5, show.legend = F) +
scale_fill_manual(values = c("Attaining" = "#99FF99","Insufficient Information" = "#FFFF99", "Non Attaining" = "#FF9999", "Not Applicable" = "orange"),labels=c("Attaining ",
"Insufficient Information ",
"Non Attaining "))
if (sum(parameter_df$prop < .10) > 0) {
pie_chart <- pie_chart + geom_text_repel(data = small_perc, aes(label = perc), size= 5, show.legend = F, nudge_x = nudgex,nudge_y = nudgey)
}
pie_chart
}
#Indivdual pie charts to create combined pie charts
pie_do <- parameter_pie_chart('DO')
pie_TP<-parameter_pie_chart('Total Phosphorus')
pie_temp<-parameter_pie_chart('Temperature')
pie_pH<-parameter_pie_chart('pH')
pie_arcs<-parameter_pie_chart('Arsenic-HH')
pie_TDS<-parameter_pie_chart('Total Dissolved Solids')
pie_causebio<-parameter_pie_chart('Biological (Cause Unknown)')
pie_human_lead<-parameter_pie_chart('Lead-HH - DWS')
pie_mercury<-parameter_pie_chart('Mercury-HH')
pie_nitrate<-parameter_pie_chart('Nitrate')
pie_aluminum <- parameter_pie_chart("Aluminum")
pie_temp_trout<-parameter_pie_chart('Temperature Trout')
pie_do_trout<-parameter_pie_chart('DO Trout')
pie_fish_merc<-parameter_pie_chart('Fish-Mercury')
pie_fish_ddt<-parameter_pie_chart('Fish-DDx')
pie_fish_dioxin<-parameter_pie_chart('Fish-Dioxin')
pie_fish_chlordane<-parameter_pie_chart('Fish-Chlordane')
pie_fish_pcb<-parameter_pie_chart('Fish-PCB')
pie_human_arsenic<-parameter_pie_chart('Arsenic-HH')
pie_TDS<-parameter_pie_chart('Total Dissolved Solids')
pie_arsenic_dws<-parameter_pie_chart('Arsenic HH - DWS')
pie_trout_do<-parameter_pie_chart('DO Trout')
pie_unknown_trout<-parameter_pie_chart('Biological Trout (Cause Unknown)')
pie_ecoli<-parameter_pie_chart('e.Coli')
pie_enterococcus<-parameter_pie_chart('Enterococcus')
pie_beach_enterococcus<-parameter_pie_chart('Beach Closing (Enterococcus)')
##Figure 2.10
combined_plot1 <- plot_grid(pie_human_arsenic + theme(legend.position="none"),
pie_TDS + theme(legend.position = "none"),
pie_human_lead + theme(legend.position = "none"),
pie_mercury + theme(legend.position = "none"),
pie_nitrate + theme(legend.position = "bottom"),
nrow = 2,ncol=3,align="hv",labels=c("Arsenic,human health","TDS","Lead,human health","Mercury,human health","Nitrate"),label_fontface="bold",label_size=10,hjust=-0.3,vjust=9)+
draw_label("Figure 2.10:Assessment Results for Key Parameters Associated with Water Supply Use,\nPercent(%) of 826 AUs",fontface="bold",hjust=0.5,vjust=-14.5)
ggsave(filename="Figure2.10-Water Supply Use.pdf",path="V:/lum/WM&S/BEAR (Bureau of Environmental Analysis and Restoration)/Envpln/Hourly Employees/KevinZolea/Rwork/2014IR/PieCharts",width=11.5,height=11)
`
Plot that I have:
Plot I Want:
I have used the following example for my question:
http://www.cmap.polytechnique.fr/~lepennec/R/Radar/RadarAndParallelPlots.html
mtcarsscaled <- as.data.frame(lapply(mtcars, ggplot2:::rescale01))
mtcarsscaled$model <- rownames(mtcars)
mtcarsmelted <- reshape2::melt(mtcarsscaled)
coord_radar <- function (theta = "x", start = 0, direction = 1)
{
theta <- match.arg(theta, c("x", "y"))
r <- if (theta == "x")
"y"
else "x"
ggproto("CordRadar", CoordPolar, theta = theta, r = r, start = start,
direction = sign(direction),
is_linear = function(coord) TRUE)
}
plot <- ggplot(mtcarsmelted, aes(x = variable, y = value)) +
geom_polygon(aes(group = model, color = model), fill = NA, size = 2, show.legend = FALSE) +
geom_line(aes(group = model, color = model), size = 2) +
theme(strip.text.x = element_text(size = rel(0.8)),
axis.text.x = element_text(size = rel(0.8)),
axis.ticks.y = element_blank(),
axis.text.y = element_blank()) +
xlab("") + ylab("") +
guides(color = guide_legend(ncol=2)) +
coord_radar()
print(plot)
How can I define limits for the y axis? Currently, the lowest value will be in the middle of the radar plot and zero will not be indicated. I would like zero to be in the middle rather than the middle/center of the plot to be the lowest value.
Any help is much appreciated!
I figured out it simply worked with
scale_y_continuous(limits=c(0,10), breaks=c(1,2,3,4,5,6,7,8,9,10))
... but I had to change the values into as.numeric beforehand.