I saw a picture of a chart below and would like to recreate something similar. My code is below, how would I got about creating a multi-layer donut plot that shows me the percentage of each group?
data <- data.frame(Specialty = c("Neuro-oncologist", "Neurosurgeon", "Radiation-oncologist"),Percentage = c(44.2, 69.6, 17.2))
Surely there is a better way to do it, but if you separate your data in three independent dataframes, show the three dataset in stacked bars and finally change coordinates to polar can get this:
Code:
data1 <- data.frame(Specialty = c("Neuro-oncologist", ""),Percentage = c(44.2, 100-44.2))
data2 <- data.frame(Specialty = c("Neurosurgeon", ""),Percentage = c(69.6, 100-69.6))
data3 <- data.frame(Specialty = c("Radiation-oncologist", ""),Percentage = c(17.2, 100-17.2))
plt <- ggplot() + geom_col(aes(x = 2, y = Percentage, fill = Specialty),
data = data1, color = "white") +
geom_text(aes(label = Percentage, x= 2, y = Percentage), data = data1, size = 3) +
geom_col(aes(x = 3, y = Percentage, fill = Specialty),
data = data2, color = "white") +
geom_text(aes(label = Percentage, x= 3, y = Percentage), data = data2, size = 3) +
geom_col(aes(x = 4, y = Percentage, fill = Specialty),
data = data3, color = "white") +
geom_text(aes(label = Percentage, x= 4, y = Percentage), data = data3, size = 3) +
xlim(0, 4.5) + labs(x = NULL, y = NULL) +
theme(axis.ticks=element_blank(),
axis.text=element_blank(),
axis.title=element_blank())
plt + coord_polar(theta = "y")
Related
I've been trying for a while now and also doing a lot of research, but I just can't get it to add a simple legend for my two lines.
I have two lines in my chart and I just want to add a legend for the two lines.
scale_color_manual did not work. I suspect it is because I am using scale_y_break. In other plots (without scale_y_break) scale_color_manual works without problems.
Here is my code:
day <- c(1:5)
altimeter <- c(8.291, 8.872, 7.212, 8.1, 5.92)
slope_kilometers <- c(30.23, 34.8, 29.34, 32.98, 21.23)
df2 <- data.frame(day, altimeter, slope_kilometers)
library(ggbreak)
altimeter_color <- "steelblue"
slope_kilometers_color <- "darkred"
ggplot(df2, aes(x = day)) +
#Altimeter data
geom_line(aes(y = altimeter),
linetype = 2,
linewidth = 1,
color = altimeter_color) +
geom_point(y = altimeter, size = 3, color = altimeter_color) +
#Slope kilometers data
geom_line(aes(y = slope_kilometers),
linetype = 2,
linewidth = 1,
color = slope_kilometers_color) +
geom_point(y = slope_kilometers, size = 3, color = slope_kilometers_color) +
#Y-Axis
scale_y_break( c(9, 20), scales = 1.5) +
#Label
labs(x = "Tage",
y = "[km]") +
#Legend
scale_color_manual(values = c(altimeter_color, slope_kilometers_color)) +
#Title
ggtitle("Höhenmeter und Pistenkilometer meines 5-tägigen Skiurlaubs")
I tried different versions of scale_color_manual, labs, aes(fill="")
Update: I tweaked the former plot (removed):
One way to achieve what you want is:
First bring data in long format then put color inside aesthetics:
Rule of thumb: What is in aesthetics will have a legend:
library(tidyverse)
library(ggbreak)
df2 %>%
pivot_longer(-day) %>%
ggplot(aes(x = day)) +
#Altimeter data
geom_line(data = . %>% filter(name == "altimeter"), aes(y = altimeter, color = name),
linetype = 2, linewidth = 1 ) +
geom_point(data = . %>% filter(name == "altimeter"), aes(y = altimeter, color = name), size = 3) +
#Slope kilometers data
geom_line(data = . %>% filter(name == "slope_kilometers"), aes(y = slope_kilometers, color = name),
linetype = 2, linewidth = 1) +
geom_point(data = . %>% filter(name == "slope_kilometers"), aes(y = slope_kilometers, color = name), size = 3) +
#Y-Axis
scale_y_break( c(9, 20), scales = 1.5) +
#Label
labs(x = "Tage", y = "[km]", color = "") +
#Legend
scale_color_manual(values = c(altimeter_color, slope_kilometers_color)) +
#Title
ggtitle("Höhenmeter und Pistenkilometer meines 5-tägigen Skiurlaubs") +
theme(legend.position = "bottom")
I am confused of this problem for a long time. A simple data frame is constructed as follows
data <- data.frame(
x = 1:5,
y = 5:1,
fill = c(rep("pink", 3), rep("blue", 2)),
shape = c(rep(21, 3), rep(22, 2))
)
Suppose I wand to show the legend of the fill
uniFill <- unique(data$fill)
p <- ggplot(data,
mapping = aes(x = x,
y = y,
fill = fill)) +
geom_point(shape = data$shape) +
# show legend so that I do not call `scale_fill_identity()`
scale_fill_manual(values = uniFill,
labels = uniFill,
breaks = uniFill)
p
The graphics are OK, however, the legend is not correct
I guess, maybe different shapes (21 to 25) cannot be merged? Then, I partition the data into two subsets where the first set has shape 21 and the second has shape 22.
data1 <- data[1:3, ]
data2 <- data[4:5, ]
# > data1$shape
# [1] 21 21 21
# > data2$shape
# [1] 22 22
ggplot(mapping = aes(x = x,
y = y,
fill = fill)) +
geom_point(data = data1, shape = data1$shape) +
geom_point(data = data2, shape = data2$shape) +
scale_fill_manual(values = uniFill,
labels = uniFill,
breaks = uniFill)
Unfortunately, the legend does not change. Then, I changed the shape from a vector to a scalar, as in
ggplot(mapping = aes(x = x,
y = y,
fill = fill)) +
geom_point(data = data1, shape = 21) +
geom_point(data = data2, shape = 22) +
scale_fill_manual(values = uniFill,
labels = uniFill,
breaks = uniFill)
The legend of the fill color is correct finally...
So what happens here? Is it a bug? Is it possible to just add a single layer but with different shapes (21 to 25)?
A possible solution is that one can add component guides(), as in
p +
guides(fill = guide_legend(override.aes = list(fill = uniFill,
shape = 21)))
But I am more interested in why p does not work (legend)
The main reason your legend is not working in your first example is because you did not put your shape in the aesthetics.
I have a couple other suggestions: Do not define colors in your data frame; instead define a column to change the aesthetics using a code. Then define your fill and shape values explicitly. Each of the scales needs to have the same name - in this case "Legend."
Give this edit a try.
data <- data.frame(
x = 1:5,
y = 5:1,
fill = c(rep("p", 3), rep("b", 2))
)
uniFill <- c("p"="pink", "b"="blue")
uniShape <- c("p" = 21, "b" = 22)
p <- ggplot(data,
mapping = aes(x = x,
y = y,
fill = fill,
shape = fill)) +
geom_point() +
# show legend so that I do not call `scale_fill_identity()`
scale_fill_manual("Legend",values = uniFill,
labels = uniFill)+
scale_shape_manual("Legend",values = uniShape,
labels = uniFill)
p
(edit) If your fill and shape aesthetics do not match up, I don't see any other way than to use guides and two legends. Notice that if your attribute column is descriptive, you do not need to set the labels and your code will be cleaner (see shape vs fill aesthetics).
data <- data.frame(
x = 1:5,
y = 5:1,
fill = c(rep("p", 3), rep("b", 2)),
shape = c(rep("circles", 2), rep("squares", 3))
)
uniFill <- c("p"="pink", "b"="blue")
uniShape <- c("circles" = 21, "squares" = 22)
p <- ggplot(data,
mapping = aes(x = x,
y = y,
fill = fill,
shape = shape)) +
geom_point() +
# show legend so that I do not call `scale_fill_identity()`
scale_fill_manual("Legend fill",values = uniFill,
labels = uniFill)+
scale_shape_manual("Legend shape",values = uniShape )+
guides(fill = guide_legend("Legend fill", override.aes = list(shape = 21)))
p
I have a plot like this:
library("ggplot2")
library("ggtext")
df = data.frame(x = rnorm(n=12), y = rnorm(n=12),
groupshape = rep(c("a","b","c"), 4),
groupcol = rep(c("e","d","f"), 4))
p = ggplot(df, aes(x = x,y = y,
shape = groupshape,
color = groupcol)) +
geom_point() + theme_classic() + labs(shape = "shape", color = "color")
Producing a plot like this:
But I want to know how to get something like this with the legend:
How would I do that? I can get rid of the shape itself through guides by turning them all while, but then the text just hovers menacingly without alignment to the legend below.
This could be achieved via the label.position and the label.theme arguments of guide_legend:
library("ggplot2")
library("ggtext")
df = data.frame(x = rnorm(n=12), y = rnorm(n=12),
groupshape = rep(c("a","b","c"), 4),
groupcol = rep(c("e","d","f"), 4))
ggplot(df, aes(x = x,y = y,
shape = groupshape,
color = groupcol)) +
geom_point() + theme_classic() + labs(shape = "shape", color = "color") +
guides(color = guide_legend(label.position = "left", label.theme = element_text(face = "bold")),
shape = guide_legend(label.position = "left"))
I am creating a plot that has 2 legends using both ggplot2 and ggnewscale. What I'm trying to achieve is to fix the order of the separate legends so they always appear in the same order. The images and code below show a basic example of the issue I'm having.
First, create some data and set the colour palettes:
df <- data.frame(x = c(1:5), y = runif(10))
df_1 <- data.frame(x = c(1:5), y = runif(10))
pal_1 = rev(colorspace::sequential_hcl(palette = "Blues 3", n = 10))
pal_2 = rev(colorspace::sequential_hcl(palette = "Reds 3", n = 10))
Now create a plot (note the limits I set are between 0 and 1 for the legends):
library(ggplot2)
library(ggnewscale)
ggplot(df, mapping = aes(x, y)) +
geom_point(size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_1, limits = c(0,1), name = "val1") +
new_scale_fill() +
geom_point(data = df_1, size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_2, limits = c(0,1), name = "val2")
This will result in the following image (note that the legend for val1 is on the top):
Now, if we change the limits for val2 to something larger, like so:
ggplot(df, mapping = aes(x, y)) +
geom_point(size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_1, limits = c(0,1), name = "val1") +
new_scale_fill() +
geom_point(data = df_1, size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_2, limits = c(0,10), name = "val2")
We will get this (note that val2 legend is now on top:
It seems that ggplot will put the legend with the larger limit range on the top. I was wonder if there was a way to fix the legend order so that, say val1 is always on the top... no matter the range of the limits?
You could specify the order of the legends via the order argument of guide_xxx:
df <- data.frame(x = c(1:5), y = runif(10))
df_1 <- data.frame(x = c(1:5), y = runif(10))
pal_1 = rev(colorspace::sequential_hcl(palette = "Blues 3", n = 10))
pal_2 = rev(colorspace::sequential_hcl(palette = "Reds 3", n = 10))
library(ggplot2)
library(ggnewscale)
ggplot(df, mapping = aes(x, y)) +
geom_point(size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_1, limits = c(0,1), name = "val1",
guide = guide_colorbar(order = 1)) +
new_scale_fill() +
geom_point(data = df_1, size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_2, limits = c(0,10), name = "val2",
guide = guide_colorbar(order = 2))
I've got a bubble grid chart created but I can't for the life of my change the colors of the fill. I want to use a rainbow gradient based on the values. Below is my code and I've attached image out my output
setwd("C:/Users/Schelly/Desktop/Projects/Jens_tables_and_figures_2020/Bubble_chart")
library(tidyverse)
library(reshape2)
pc <- read.csv("Para_Bubble_data2.csv", header = TRUE)
head(pc)
pcm<-melt(pc, id = c("Sample"))
pcm$Sample <- factor(pcm$Sample,levels=unique(pcm$Sample))
xx = ggplot(pcm, aes(x = Sample, y = variable)) +
geom_point(aes(size = value, fill = value), alpha = 0.75, shape = 21) +
scale_colour_gradientn(colours=rainbow(4))+
scale_size_continuous(limits = c(0.000001, 1), range = c(1,17), breaks = c(.01,.10,.50,.75)) +
labs( x= "", y = "", size = "Relative Abundance (%)", fill = "")
xx
Output of code
You need to specify aes(colour = value) if you want to use scale_color_gradientn:
library(ggplot2)
df <- data.frame(x = factor(rep(1:5, each = 6)),
y = factor(rep(1:6, 5)), val = sample(30))
ggplot(df, aes(x = x, y = y, size = val, colour = val)) +
geom_point() +
scale_color_gradientn(colours = c("red", "yellow", "blue"))
If you want to use fill (to preserve a different outline colour), you need to use scale_fill_gradientn:
ggplot(df, aes(x = x, y = y, size = val)) +
geom_point(aes(size = val, fill = val), alpha = 0.75, shape = 21) +
scale_fill_gradientn(colours = rainbow(4))+
labs( x= "", y = "", size = "Relative Abundance (%)", fill = "")