Reputation: 6220
This is a followup question to this post.
I have an R
data.frame
where each row describes a composition that I want to plot as a pie on an xy plane. I want to color-code the slices of each pie by their y.a_1
, y.a_2
, y.a_3
, y.a_4
, y.b_1
, y.b_2
, y.b_3
, y.b_4
, o.a_1
, o.a_3
, o.a_4
, o.b_1
, o.b_3
, o.b_4
, in the example df
below. The class
column used in this post is not included in df
at this point because it is not a pie-specific property but rather a property of the slices, and is created below.
Here's the df
:
library(dplyr)
set.seed(1)
df <- data.frame(x = runif(10, 0, 100), y = runif(10, 0, 100), id = paste0("id",1:10),
y.a_1 = as.integer(runif(10, 0, 100)), y.a_2 = as.integer(runif(10, 0, 100)), y.a_3 = as.integer(runif(10, 0, 100)), y.a_4 = as.integer(runif(10, 0, 100)),
y.b_1 = as.integer(runif(10, 0, 100)), y.b_2 = as.integer(runif(10, 0, 100)), y.b_3 = as.integer(runif(10, 0, 100)), y.b_4 = as.integer(runif(10, 0, 100)),
o.a_1 = as.integer(runif(10, 0, 100)), o.a_3 = as.integer(runif(10, 0, 100)), o.a_4 = as.integer(runif(10, 0, 100)),
o.b_1 = as.integer(runif(10, 0, 100)), o.b_3 = as.integer(runif(10, 0, 100)), o.b_4 = as.integer(runif(10, 0, 100))) %>%
dplyr::mutate(size = runif(10,0.002,0.01)*(y.a_1 + y.a_2 + y.a_3 + y.a_4 + y.b_1 + y.b_2 + y.b_3 + y.b_4 + o.a_1 + o.a_3 + o.a_4 + o.b_1 + o.b_3 + o.b_4))
Following Allan Cameron's solution I define this function for creating pie polygons:
make_pie <- function(x, y, size, groups, n, rownum) {
angles <- c(0, 2*pi * cumsum(n)/sum(n))
do.call("rbind", Map(function(a1, a2, g) {
xvals <- c(0, sin(seq(a1, a2, len = 30)) * size, 0) + x
yvals <- c(0, cos(seq(a1, a2, len = 30)) * size, 0) + y
data.frame(x = xvals, y = yvals, group = g, rownum = rownum)
}, head(angles, -1), tail(angles, -1), groups))
}
Again, class
is not included in this function because it was not part of df
.
However, I add a class
column to the data.frame
created by running df
through the make_pie
function:
df <- df %>%
mutate(r = row_number()) %>%
rowwise() %>%
group_map(~ with(.x, make_pie(x, y,
size, c("y.a_1", "y.a_2", "y.a_3", "y.a_4", "y.b_1", "y.b_2", "y.b_3", "y.b_4", "o.a_1", "o.a_3", "o.a_4", "o.b_1", "o.b_3", "o.b_4"),
c(y.a_1, y.a_2, y.a_3, y.a_4, y.b_1, y.b_2, y.b_3, y.b_4, o.a_1, o.a_3, o.a_4, o.b_1, o.b_3, o.b_4), r))) %>%
bind_rows() %>%
mutate(class = gsub("\\.a","",group) %>% gsub("\\.b","",.)) %>% unique()
df$group <- factor(df$group, levels = c("y.a_1", "y.a_2", "y.a_3", "y.a_4", "y.b_1", "y.b_2", "y.b_3", "y.b_4", "o.a_1", "o.a_3", "o.a_4", "o.b_1", "o.b_3", "o.b_4"))
df$class <- factor(df$class, levels = c("y_1", "y_2", "y_3", "y_4", "o_1", "o_3", "o_4"))
Then I use this ggplot2
and ggpattern
function:
library(ggplot2)
library(ggpattern)
ggplot(df,aes(x, y, fill = group, group = interaction(group, rownum))) +
geom_polygon_pattern(aes(pattern = class), pattern_fill = "black",
pattern_angle = 45, pattern_spacing = 0.01,
pattern_density = 0.1) +
scale_fill_manual(values = c("#FFEFDE", "#FFBFB1", "#FF8F84", "#FF5550", "#B6EDFF", "#98D6F3", "#7CC0E1", "#5BA7CD",
"#D11110", "#AA0003", "#70000A", "#2B7196", "#1A5B81", "#0F4769")) +
guides(pattern = guide_legend(override.aes = list(fill = "white"))) +
coord_equal() +
theme_void()
It's close to what I want but I'm trying to figure out how to solve these issues:
class
es I have) instead of the 3 it is currently giving?y_1
, y_2
, y_3
, y_4
class
es and white for the o_1
, o_3
, and o_4
class
es?Upvotes: 0
Views: 137