R中的三层环形图

6

我正在尝试在R中重新创建这个图像,但是我无法弄清楚如何将甜甜圈图层分为3层 - 我找到的所有内容(例如,webr :: PieDonut)都只允许2层。使用ggplot也无法重新创建。

enter image description here

一个MRE是:
library(ggplot2)
library(webr)
library(dplyr)

lexicon <- data.frame("Level1" = c(rep("Flavour", 11), rep("Appearance", 4)),
                  "Level2" = c(rep("Misc", 6), rep("Pungent", 5), rep("Colour", 4)),
                  "Level3" = c("Fresh", "Refreshing", "Soapy", "Minty", "Nutty", "Milky", "Peppery", "Sharp", "Horseradish", "Mustard hot", "Spicy", "Colourful"," Fresh Green", "Dark Green", "Bright Green")
)

PieDonut(lexicon, aes(Level1, Level2), title = "Salad Lexicon", showRatioDonut =FALSE, showRatioPie = FALSE)

ggplot(lexicon, aes(Level2, Level3, fill = Level1)) +
  geom_col() +
  scale_fill_viridis_d() +
  coord_polar("y")

虽然 PieDonut 适用于两个级别(未显示),但它不允许包括最终级别。正如下图所示,ggplot 方法也无法解决该问题。

enter image description here

我该如何在R中获得这种类型的图表?可以使用ggplot或基础绘图。
2个回答

11

我认为一个不错的替代方案是,在一些数据处理之后使用geom_rect。使用填充、颜色和透明度比例尺可以帮助改善类别的区分度。在这里,我还会使用geom_textpath,不过如果有足够的空间,我可能会选择圆周标签:

lexicon %>%
  mutate(top_level = Level1) %>%
  pivot_longer(1:3) %>%
  group_by(name, value) %>%
  mutate(width = n()) %>%
  unique() %>%
  arrange(name) %>%
  group_by(name) %>%
  mutate(ymid = as.numeric(sub("\\D+", "", name)),
         ymax = ymid + 0.5, ymin = ymid - 0.5,
         xmin = c(0, head(cumsum(width), -1)),
         xmax = cumsum(width),
         xmid = (xmax + xmin) / 2) %>%
  ggplot(aes(xmid, ymid, fill = top_level)) +
  geom_rect(aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax,
                alpha = name, color = top_level)) +
  geomtextpath::geom_textpath(aes(y = ymid + 0.25, label = value, 
                                  group = value)) +
  scale_alpha_manual(values = c(1, 0.3, 0.1)) +
  scale_fill_manual(values = c("#cd9900", "#00817e")) +
  scale_colour_manual(values = c("#cd9900", "#00817e")) +
  scale_y_continuous(limits = c(-0.5, 3.6)) +
  coord_polar() +
  theme_void() +
  theme(legend.position = "none")

enter image description here


真不错,Allan。我也尝试过使用周向标签,但是在geom_col中失败了。将记住使用geom_rect的技巧。 - stefan
谢谢您提供这个。看起来非常不错。请问您能告诉我如何使文本成为径向而不是周向吗?我尝试了一些方法,但它们似乎不起作用,而且我对ggplot和这些函数都不熟悉。 - Beavis
@Beavis 在 geom_textpath 中使用 angle = 90 - Allan Cameron
@AllanCameron。经过进一步检查,当使用重复值时(例如,“Earthy”既是口味类别又是原始图中的余味->口感。这似乎破坏了这种方法 - 你知道如何避免这种情况吗(不更改值)?我尝试了一些方法,比如尝试为组合使用UID,但似乎不起作用。 - Beavis

8

一种方法是将数据重塑为长格式,并在传递给ggplot之前进行一些手动聚合。此外,我使用geomtextpath::geom_textpath来添加标签:

library(ggplot2)
library(dplyr)
library(geomtextpath)

lexicon <- data.frame("Level1" = c(rep("Flavour", 11), rep("Appearance", 4)),
                      "Level2" = c(rep("Misc", 6), rep("Pungent", 5), rep("Colour", 4)),
                      "Level3" = c("Fresh", "Refreshing", "Soapy", "Minty", "Nutty", "Milky", "Peppery", "Sharp", "Horseradish", "Mustard hot", "Spicy", "Colourful"," Fresh Green", "Dark Green", "Bright Green")
)

lexicon_long <- lexicon |>
  mutate(fill = Level1) |>
  tidyr::pivot_longer(-fill, names_to = "level", values_to = "label") |>
  mutate(label = forcats::fct_inorder(label)) |> 
  count(fill, level, label) |>
  group_by(level) |>
  mutate(pct = n / sum(n))

ggplot(lexicon_long, aes(level, pct, fill = fill)) +
  geom_col(color = "white") +
  geom_textpath(aes(label = label, group = label),
                position = position_stack(vjust = .5),
                upright = TRUE, hjust = .5, size = 3
  ) +
  scale_fill_viridis_d() +
  coord_polar("y") +
  theme_void() +
  guides(fill = "none")

enter image description here


2
很高兴看到有一个geomtextpath的解决方案 :) - Allan Cameron
这似乎破坏了数据的结构。在每个环中,值都是字母表顺序的,而不是与相关层相关的。 - Beavis
我的错。如果你想要一个特定的顺序,你必须使用一个 factor。我刚刚进行了编辑并在重塑后使用了 fct_inorder,以便保留你的类别顺序。 - stefan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接