Nothing
#' Create donut plot.
#'
#' @param data Data frame contains full data or summarized data.
#' @param group_key Column used to summarize the data. Default: NULL.
#' @param count_type Data frame type, chosen from "count" and "full". "count" means summarized data and "full" means full data. Default: count.
#' @param fill_color Colors used. Default: NULL (conduct automatic selection).
#' @param label_info Label information type, chosen from count, ratio and all (count and ratio). Default: count.
#' @param label_split Pattern used to split the label, support regular expression. Default: space.
#' @param label_len The length of label text. Used when \code{label_split} is NULL. Default: 40.
#' @param label_color Color of the label. Default: black.
#' @param label_type Label style, chosen from circle, horizon and none (no label). Default: circle.
#' @param label_pos Label position, chosen from in and out. Default: in.
#' @param label_gap Gap between label and pie plot, used when \code{label_pos} is out.
#' @param label_threshold Threshold of the ratio to determine label position (in/out pie). Default: NULL.
#' @param label_size Size of the label. Default: 4.
#' @param border_color Border color. Default: black.
#' @param border_size Border thickness. Default: 1.
#' @param r0 The radius of inner blank circle. Default: 1.
#' @param r1 The radius of outer circle. Default: 3.
#' @param donut.label Logical value, whether to show total number in the center of the plot. Default: TRUE.
#' @param donut.label.size The label size of center label. Default: 4.
#' @param donut.label.color The color of center label. Default: red.
#' @param nudge_x Parameter of \code{\link{geom_text_repel}}. Default: 1.
#' @param nudge_y Parameter of \code{\link{geom_text_repel}}. Default: 1.
#'
#' @return A ggplot2 object.
#' @importFrom dplyr mutate group_by summarise n
#' @importFrom rlang .data
#' @importFrom magrittr %>%
#' @importFrom grDevices colorRampPalette
#' @importFrom RColorBrewer brewer.pal
#' @importFrom scales percent
#' @importFrom stringr str_wrap
#' @import ggplot2
#' @importFrom ggrepel geom_text_repel
#'
#' @export
#'
#' @examples
#' library(ggpie)
#' library(ggplot2)
#' data(diamonds)
#' # circle label and out of pie
#' ggdonut(
#' data = diamonds, group_key = "cut", count_type = "full",
#' label_info = "all", label_type = "circle",
#' label_size = 4, label_pos = "out"
#' )
#' # circle label and in pie plot, with no split
#' ggdonut(
#' data = diamonds, group_key = "cut", count_type = "full",
#' label_info = "all", label_type = "circle", label_split = NULL,
#' label_size = 4, label_pos = "in"
#' )
#' # horizon label and in pie plot, with no split
#' ggdonut(
#' data = diamonds, group_key = "cut", count_type = "full",
#' label_info = "all", label_type = "horizon", label_split = NULL,
#' label_size = 4, label_pos = "in"
#' )
#' # horizon label and in pie plot
#' ggdonut(
#' data = diamonds, group_key = "cut", count_type = "full",
#' label_info = "all", label_type = "horizon",
#' label_size = 4, label_pos = "in"
#' )
#' # horizon label and out of pie plot, with no split
#' ggdonut(
#' data = diamonds, group_key = "cut", count_type = "full",
#' label_info = "all", label_type = "horizon", label_split = NULL,
#' label_size = 4, label_pos = "out"
#' )
#' # horizon label and out of pie plot
#' ggdonut(
#' data = diamonds, group_key = "cut", count_type = "full",
#' label_info = "all", label_type = "horizon",
#' label_size = 4, label_pos = "out"
#' )
#' # with label threshold
#' ggdonut(
#' data = diamonds, group_key = "cut", count_type = "full",
#' label_info = "all", label_type = "horizon", label_split = NULL,
#' label_size = 4, label_pos = "in", label_threshold = 10
#' )
#' ggdonut(
#' data = diamonds, group_key = "cut", count_type = "full",
#' label_info = "all", label_type = "horizon",
#' label_size = 4, label_pos = "in", label_threshold = 10
#' )
ggdonut <- function(data, group_key = NULL, count_type = c("count", "full"), fill_color = NULL, label_info = c("count", "ratio", "all"),
label_split = "[[:space:]]+", label_len = 40, label_color = "black",
label_type = c("circle", "horizon", "none"), label_pos = c("in", "out"), label_gap = 0.05,
label_threshold = NULL, label_size = 4, border_color = "black", border_size = 1,
r0 = 1, r1 = 3, donut.label = TRUE, donut.label.size = 4, donut.label.color = "red",
nudge_x = 1, nudge_y = 1) {
# check parameters
count_type <- match.arg(arg = count_type)
label_info <- match.arg(arg = label_info)
label_type <- match.arg(arg = label_type)
label_pos <- match.arg(arg = label_pos)
# prepare plot data
plot.data <- PrepareData(
data = data, group_key = group_key, count_type = count_type, fill_color = fill_color,
label_info = label_info, label_split = label_split, label_len = label_len, label_color = label_color
)
data <- plot.data[["data"]]
fill_color <- plot.data[["fill_color"]]
label_color <- plot.data[["label_color"]]
# create circle label plot
if (label_type == "circle") {
data$preangle <- (cumsum(data$count) - 0.5 * data$count) / sum(data$count) * 360
data$angle <- data$preangle %% 180 - 90
data$CumSum <- rev(round(cumsum(rev(data$count)) - rev(data$count / 2), 2))
if (label_pos == "out") {
pie_plot <- ggplot() +
geom_bar(data,
mapping = aes(x = (r0 + r1) / 2, y = count, fill = group),
width = r1 - r0, stat = "identity", color = border_color, size = border_size
) +
xlim(0, NA) +
geom_text(data,
mapping = aes(x = r1 + label_gap, y = CumSum, label = label, angle = angle, colour = group), show.legend = FALSE,
hjust = ifelse(data$preangle > 180, 0, 1), size = label_size
) +
coord_polar(theta = "y", start = 0, clip = "off") +
theme_void() +
scale_fill_manual(values = fill_color) +
scale_colour_manual(values = label_color)
} else if (label_pos == "in") {
pie_plot <- ggplot() +
geom_bar(data,
mapping = aes(x = (r0 + r1) / 2, y = count, fill = group),
width = r1 - r0, stat = "identity", color = border_color, size = border_size
) +
xlim(0, NA) +
geom_text(data,
mapping = aes(x = (r0 + r1) / 2, y = CumSum, label = label, angle = angle, colour = group),
show.legend = FALSE, size = label_size
) +
coord_polar(theta = "y", start = 0, clip = "off") +
theme_void() +
scale_fill_manual(values = fill_color) +
scale_colour_manual(values = label_color)
}
}
# create horizon label plot
if (label_type == "horizon") {
data <- data %>%
dplyr::mutate(Freq = count * 100 / sum(count)) %>%
dplyr::mutate(CumFreq = rev(round(cumsum(rev(Freq)) - rev(Freq / 2), 2)))
if (label_pos == "out") {
pie_plot <- ggplot() +
geom_bar(data,
mapping = aes(x = (r0 + r1) / 2, y = Freq, fill = group),
width = r1 - r0, stat = "identity", color = border_color, size = border_size
) +
xlim(0, NA) +
geom_text_repel(
data = data,
mapping = aes(label = label, y = CumFreq, x = after_stat(r1), colour = group), show.legend = FALSE,
size = label_size, point.padding = NA, max.overlaps = Inf, nudge_x = nudge_x, nudge_y = nudge_y,
segment.curvature = -0.2, segment.ncp = 10, segment.angle = 20
) +
coord_polar(theta = "y", start = 0, clip = "off") +
theme_void() +
scale_fill_manual(values = fill_color) +
scale_colour_manual(values = label_color)
} else if (label_pos == "in") {
if (is.null(label_threshold)) {
pie_plot <- ggplot() +
geom_bar(data,
mapping = aes(x = (r0 + r1) / 2, y = Freq, fill = group),
width = r1 - r0, stat = "identity", color = border_color, size = border_size
) +
xlim(0, NA) +
geom_text_repel(
data = data,
mapping = aes(x = (r0 + r1) / 2, y = CumFreq, label = label, colour = group),
show.legend = FALSE, size = label_size
) +
coord_polar(theta = "y", start = 0, clip = "off") +
theme_void() +
scale_fill_manual(values = fill_color) +
scale_colour_manual(values = label_color)
} else {
pie_plot <- ggplot() +
geom_bar(data,
mapping = aes(x = (r0 + r1) / 2, y = Freq, fill = group),
width = r1 - r0, stat = "identity", color = border_color, size = border_size
) +
xlim(0, NA) +
geom_text_repel(
data = data[data$Freq < label_threshold, ],
aes(label = label, y = CumFreq, x = after_stat(r1), colour = group), show.legend = FALSE,
size = label_size, point.padding = NA, max.overlaps = Inf, nudge_x = nudge_x, nudge_y = nudge_y,
segment.curvature = -0.2, segment.ncp = 10, segment.angle = 20
) +
geom_text(
data = data[data$Freq >= label_threshold, ],
aes(y = CumFreq, x = (r0 + r1) / 2, label = label, colour = group),
show.legend = FALSE, size = label_size
) +
coord_polar(theta = "y", start = 0, clip = "off") +
theme_void() +
scale_fill_manual(values = fill_color) +
scale_colour_manual(values = label_color)
}
}
}
# create with no label
if (label_type == "none") {
pie_plot <- ggplot() +
geom_bar(data,
mapping = aes(x = (r0 + r1) / 2, y = count, fill = group),
width = r1 - r0, stat = "identity", color = border_color, size = border_size
) +
xlim(0, NA) +
coord_polar(theta = "y", start = 0, clip = "off") +
theme_void() +
scale_fill_manual(values = fill_color)
}
if (donut.label) {
pie_plot <- pie_plot + annotate("text",
x = 0, y = 0, label = paste0("Total: ", sum(data$count)),
size = donut.label.size, colour = donut.label.color
)
}
pie_plot <- pie_plot + theme(plot.margin = unit(c(1, 1, 1, 1), "lines"))
return(pie_plot)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.