英文:
layered-donut chart for a better subgroups-differentiation in R
问题
我正在尝试找到一种在R中绘制以下分层环形图的方法,以便我可以更好地区分子组。该图表是通过Excel实现的,通过生成四个不同的图层,每个子组具有不同数量的图层。
我尝试了以下方法,但效果不理想。
ggdonutchart方法
data <- as.data.frame(Titanic)
p <- data %>% group_by(Class) %>% summarise(num = sum(Freq))
ggdonutchart(p, x = "num", label = "Class", fill = "Class",
palette = c("darkblue","blue","lightblue","gray"), color = "white")
这种方法的问题在于,尝试在外部添加另一个相同的图层,即 PieDonut(PD, aes(Class, Class, count=n), title = "Titanic: Survival by Class")
,会导致错误消息:! Each row of output must be identified by a unique combination of keys.
我想使用Titanic数据集生成类似第一张图的图表,不同的颜色显示不同的组。例如,深蓝色表示头等舱的份额,蓝色表示二等舱的份额,浅蓝色表示三等舱的份额,灰色表示船员的份额。换句话说,不同的颜色具有不同的宽度。
有没有办法实现这个目标?谢谢。
英文:
I'm trying to find a way to plot the following layered-donut chart in R, so that I can differentiate the subgroups better. The graph is realized by Excel, by generating four different layers, and each subgroup has different amount of layers.
I have tried the following approach, but it is not ideal.
ggdonutchart approach
p <- data %>% group_by(Class) %>% summarise(num = sum(Freq))
ggdonutchart(p, x = "num", label = "Class", fill = "Class",
palette = c("darkblue","blue","lightblue","gray"), color = "white")
The problem with this approach is that trying to add another identical layer outside, i.e. PieDonut(PD, aes(Class, Class, count=n), title = "Titanic: Survival by Class")
, will give me the error message: ! Each row of output must be identified by a unique combination of keys.
I would like to use the Titanic dataset to generate a chart similar to the first one, with different colors showing different groups. For example, dark blue for the share of 1st class, blue for the share of 2nd class, light blue for the share of 3rd class, and gray for the share of crew class. In other words, different color has different width.
Any idea how to do this? Thank you.
答案1
得分: 2
以下是翻译好的代码部分:
library(tidyverse)
data.frame(x = rep(c('A', 'B', 'C', 'D'), times = c(4:1))) %>%
ggplot(aes(x, y = 1, fill = x)) +
geom_col(position = 'stack', color = 'white', linewidth = 0.1, width = 1) +
coord_polar() +
scale_y_continuous(limits = c(-10, 5)) +
scale_fill_manual(values = c('#1b587c', '#4ea5d8', '#c4e1f2', '#bfbfbf')) +
theme_void() +
theme(plot.background = element_rect(fill = '#f2f2f2', color = NA))
library(tidyverse)
data <- as.data.frame(Titanic)
data %>%
group_by(Class, Survived) %>%
summarise(n = sum(Freq), .groups = "drop") %>%
mutate(xmin = c(0, cumsum(head(n, -1))),
xmax = cumsum(n), ymin = 4, ymax = 5) %>%
group_by(Class) %>%
reframe(Survived = Survived, n = n, xmin = xmin, xmax = xmax,
ymin = ymin, ymax = ymax, perc = scales::percent(n / sum(n))) %>%
bind_rows(data %>%
group_by(Class) %>%
summarise(Survived = "All", n = sum(Freq), .groups = "drop") %>%
mutate(xmin = c(0, cumsum(head(n, -1))),
xmax = cumsum(n), ymin = 2, ymax = 4,
perc = scales::percent(n / sum(n)))) %>%
ggplot() +
geom_rect(aes(xmin = xmin, xmax = xmax, alpha = Survived,
ymin = ymin, ymax = ymax, fill = Class),
color = "white") +
geom_text(aes(x = (xmin + xmax)/2, y = ifelse(Survived == "All", 3, 4.5),
label = paste(ifelse(Survived == "All",
as.character(Class),
Survived), perc, sep = "\n"))) +
annotate("text", 0, 0, label = "Class", size = 8) +
scale_y_continuous(limits = c(0, 5)) +
scale_alpha_manual(values = c(1, 0.3, 0.6), guide = "none") +
guides(fill = "none") +
coord_polar() +
theme_void()
英文:
It's certainly easy enough to recreate the plot in R. I'm not sure how we would go from your data to this plot, since you haven't included it in your question, but here's a fully reproducible example of how to get the plot:
library(tidyverse)
data.frame(x = rep(c('A', 'B', 'C', 'D'), times = c(4:1))) %>%
ggplot(aes(x, y = 1, fill = x)) +
geom_col(position = 'stack', color = 'white', linewidth = 0.1, width = 1) +
coord_polar() +
scale_y_continuous(limits = c(-10, 5)) +
scale_fill_manual(values = c('#1b587c', '#4ea5d8', '#c4e1f2', '#bfbfbf')) +
theme_void() +
theme(plot.background = element_rect(fill = '#f2f2f2', color = NA))
Edit
To replicate the donut pie chart in vanilla ggplot, you probably need to shape your data into rectangles and plot them:
library(tidyverse)
data <- as.data.frame(Titanic)
data %>%
group_by(Class, Survived) %>%
summarise(n = sum(Freq), .groups = "drop") %>%
mutate(xmin = c(0, cumsum(head(n, -1))),
xmax = cumsum(n), ymin = 4, ymax = 5) %>%
group_by(Class) %>%
reframe(Survived = Survived, n = n, xmin = xmin, xmax = xmax,
ymin = ymin, ymax = ymax, perc = scales::percent(n / sum(n))) %>%
bind_rows(data %>%
group_by(Class) %>%
summarise(Survived = "All", n = sum(Freq), .groups = "drop") %>%
mutate(xmin = c(0, cumsum(head(n, -1))),
xmax = cumsum(n), ymin = 2, ymax = 4,
perc = scales::percent(n / sum(n)))) %>%
ggplot() +
geom_rect(aes(xmin = xmin, xmax = xmax, alpha = Survived,
ymin = ymin, ymax = ymax, fill = Class),
color = "white") +
geom_text(aes(x = (xmin + xmax)/2, y = ifelse(Survived == "All", 3, 4.5),
label = paste(ifelse(Survived == "All",
as.character(Class),
Survived), perc, sep = "\n"))) +
annotate("text", 0, 0, label = "Class", size = 8) +
scale_y_continuous(limits = c(0, 5)) +
scale_alpha_manual(values = c(1, 0.3, 0.6), guide = "none") +
guides(fill = "none") +
coord_polar() +
theme_void()
答案2
得分: 0
以下是翻译好的代码部分:
data <- data.frame(data.frame(stringsAsFactors=FALSE,
Group = c("A", "B", "C", "D"),
Share = c(0.25, 0.3, 0.2, 0.25)
))
data2 <- transform(data, Share = ifelse(Group == "A", 0, Share))
data3 <- transform(data2, Share = ifelse(Group == "B", 0, Share))
data4 <- transform(data3, Share = ifelse(Group == "C", 0, Share))
plt <- ggplot() + geom_col(aes(x = 2, y = Share, fill = Group),
data = data, color = "white") +
geom_col(aes(x = 2.9, y = Share, fill = Group),
data = data2, color = "white") +
geom_col(aes(x = 3.8, y = Share, fill = Group),
data = data3, color = "white") +
geom_col(aes(x = 4.7, y = Share, fill = Group),
data = data4, color = "white") +
scale_fill_manual(values = c('#bfbfbf', '#c4e1f2', '#4ea5d8', '#1b587c')) +
xlim(0, 5.5) + labs(x = NULL, y = NULL) +
theme(axis.ticks=element_blank(),
axis.text=element_blank(),
axis.title=element_blank())
plt
plt + coord_polar(theta = "y")
英文:
data <- data.frame(data.frame(stringsAsFactors=FALSE,
Group = c("A", "B", "C", "D"),
Share = c(0.25, 0.3, 0.2, 0.25)
))
data2 <- transform(data, Share = ifelse(Group == "A", 0, Share))
data3 <- transform(data2, Share = ifelse(Group == "B", 0, Share))
data4 <- transform(data3, Share = ifelse(Group == "C", 0, Share))
plt <- ggplot() + geom_col(aes(x = 2, y = Share, fill = Group),
data = data, color = "white") +
geom_col(aes(x = 2.9, y = Share, fill = Group),
data = data2, color = "white") +
geom_col(aes(x = 3.8, y = Share, fill = Group),
data = data3, color = "white") +
geom_col(aes(x = 4.7, y = Share, fill = Group),
data = data4, color = "white") +
scale_fill_manual(values = c('#bfbfbf', '#c4e1f2', '#4ea5d8', '#1b587c')) +
xlim(0, 5.5) + labs(x = NULL, y = NULL) +
theme(axis.ticks=element_blank(),
axis.text=element_blank(),
axis.title=element_blank())
plt
plt + coord_polar(theta = "y")
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论