【问题标题】:Pie charts within a list列表中的饼图
【发布时间】:2018-07-19 13:46:40
【问题描述】:

首先让我说,我知道饼图是准确显示数据的糟糕方法,但我被要求将其作为报告的一部分制作。我有一个数据集,其中包含有关位置、伤害类型以及多个个人数据字段的信息。我想显示在每个位置发生的每种伤害的百分比的饼图。我已经尝试过,其中 facility2 是通过 ServiceSite.x 拆分完整数据框创建的 52 个元素的列表。这部分有效,但创建的饼图仅包含一种“初始类型”的计数。

    summarized_list <- lapply(facility2, function(x){
  x %>% group_by(InitialType) %>% summarize(length(InitialType))
})
pies <- function(z) {
  ggplot(z, aes(x = "", fill = length(InitialType)))+ 
    geom_bar(width = 1, na.rm = TRUE)+
    coord_polar(theta = "y")
  }
lapply(summarized_list, pies)

这也部分有效,并且会很完美,但只打印出 13 个图表而不是全部 52 个

pies2 <- function(x) {
  ggplot(x, aes(x = "", fill = InitialType))+ 
    geom_bar(width = 1, na.rm = TRUE)+
    coord_polar(theta = "y")+
    xlab(x$ServiceSite.x)
}
lapply(facility2, pies2)

并给出这个错误

Error: Aesthetics must be either length 1 or the same as the data (1): x, fill

我知道第一种方法在提供正确计数的同时完美地拆分数据,我只是无法弄清楚我需要在 ggplot() 中更改什么以显示每个设施的所有伤害类型。如果可能的话,我还想添加一个百分比标签,或者至少只是计数。

Sample data: 
ServiceSite.x InitialType
2   Dermatitis
2   Diabetic
2   Pressure Injury
2   Pressure Injury
3   Pressure Injury
3   Other
3   Laceration
3   Other
4   Pressure Injury
4   MASD
4   Blister (Non-Pressure)
4   Skin Tear
4   Pressure Injury
5   Skin Tear
5   Other
5   Contusion
5   Skin Tear
5   Surgical(Non-Healing)
5   Pressure Injury
6   Pressure Injury
1   Pressure Injury
6   Pressure Injury
6   MASD
1   Surgical(Non-Healing)
1   Pressure Injury
1   Skin Tear
1   Contusion

facility2 <- split(full, full$ServiceSite.x)

这两个变量都是因子。

【问题讨论】:

  • 您的第二种方法似乎适用于您提供的示例数据。您是否确定了数据引发错误的设施有何不同?
  • @MikkoMarttila 据我所知,没有什么不同。唯一可能改变的是,并非所有设施都会记录每种类型的伤害,但这似乎不是打印的问题。
  • 也许您可以包含一些失败的数据?否则真的不可能进一步诊断。

标签: r list ggplot2 lapply


【解决方案1】:

我没有收到您所显示的错误,因此您可能需要仔细检查并找到罪魁祸首,这可能不在您发布的示例中。我使用purrr::map 而不是lapply;这部分是偏好,部分是它与管道工作流的匹配程度。我还发现map 函数很容易调试,因为它会在每个项目被映射时打印它的名称或索引;这通常可以帮助我找出问题所在。

这里的第一组图只是来自使用purrr::imap 重写您的代码,它映射到两个列表:列表本身及其名称。 split 根据ServiceSite.x 中的值命名列表,因此您现在可以访问它们来设置xlab。我不确定在设置xlabx$ServiceSite.x 时是否存在一个错误,这似乎应该返回一个完整的向量,而不仅仅是一个字符串。

library(tidyverse)
library(patchwork)

pies1 <- df %>% 
  split(.$ServiceSite.x) %>%
  imap(function(data, site) {
    ggplot(data, aes(x = "", fill = InitialType)) +
      geom_bar(width = 1) +
      coord_polar(theta = "y") +
      xlab(site)
  })

我正在使用 patchwork 库将所有​​图粘贴在一起,以便在此处显示。

reduce(pies1, `+`) + plot_layout(ncol = 2, byrow = T)

对于标签,先做一些数据准备以计算计数和百分比。在这里,我用几个 dplyr 函数做到了这一点。然后添加geom_textposition_stack(vjust = 0.5),这样文本将 1. 围绕圆圈堆叠,与条形相同,2. 在楔形中居中。我将由您自行决定文本的格式,包括添加计数标签或另外添加。

pies2 <- df %>%
  split(.$ServiceSite.x) %>%
  imap(function(data, site) {
    data %>%
      count(ServiceSite.x, InitialType) %>%
      mutate(share = round(n / sum(n), digits = 2)) %>%
      ggplot(aes(x = "", y = n, fill = InitialType)) +
        geom_col(width = 1) +
        geom_text(aes(label = scales::percent(share)), position = position_stack(vjust = 0.5)) +
        coord_polar(theta = "y") 
  })

pies2[[1]]

【讨论】:

  • 您可以通过将 group_by(ServiceSite.x, InitialType) %&gt;% summarize(count = n()) 替换为 count(ServiceSite.x, InitialType) 来降低您的代码高尔夫分数。您必须修改 mutate 语句以引用 n,因为这是 count 默认吐出的内容。
  • @JakeKaupp 你是对的,我想我需要保持分组传递到mutate 并获得正确的总和,但在这种情况下,@ 中只有一个第一组987654344@ 层次结构,所以没关系
  • @camille 在进行编辑之前效果非常好。我唯一无法解决的另一件事是如何将标签拉到图表外部。我尝试在 mutate 语句中创建一个新的 var "breaks" 并在 scale_y_continuous 但没有骰子中使用它
  • @regents 什么编辑?你将如何将标签拉到图表之外?像设置 y-breaks 而不是绘制geom_texts?休息会很尴尬,你不觉得吗?他们会在一个楔子和下一个楔子之间的边界。
猜你喜欢
  • 1970-01-01
  • 2015-08-16
  • 1970-01-01
  • 1970-01-01
  • 2012-01-02
  • 2017-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多