【问题标题】:Circular stacked barplot in R - Aesthetics must be either length 1 or the same as the data (26)R 中的圆形堆积条形图 - 美学长度必须为 1 或与数据相同 (26)
【发布时间】:2020-05-11 03:07:02
【问题描述】:

我正在尝试创建此处提到的圆形堆叠条形图 (https://www.r-graph-gallery.com/299-circular-stacked-barplot.html)。当我进入制作情节的步骤时出现以下错误(下面以粗体显示):

错误:美学长度必须为 1 或与数据相同 (26):hjust 运行rlang::last_error() 以查看发生错误的位置。 另外:警告信息: 删除了包含缺失值的 208 行 (position_stack)。

这就是我的数据的样子(5 列 70 行):

个人;团体;值1;值2;值3;价值4

这是我的代码:

以整齐的格式(长格式)转换数据

data <- data %>% gather(key = "observation", value="value", -c(1,2)) 

制作情节

p <- ggplot(data) +

  geom_bar(aes(x=as.factor(id), y=value, fill=observation), stat="identity", alpha=0.5) +
  scale_fill_viridis(discrete=TRUE) + 

  geom_segment(data=grid_data, aes(x = end, y = 0, xend = start, yend = 0), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_data, aes(x = end, y = 2, xend = start, yend = 2), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_data, aes(x = end, y = 4, xend = start, yend = 4), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_data, aes(x = end, y = 6, xend = start, yend = 6), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_data, aes(x = end, y = 8, xend = start, yend = 8), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +

  ggplot2::annotate("text", x = rep(max(data$id),5), y = c(0, 2, 4, 6, 8), label = c("0", "2", "4", "6", "8") , color="grey", size=6 , angle=0, fontface="bold", hjust=1) +

  ylim(-150,max(label_data$tot, na.rm=T)) +
  theme_minimal() +
  theme(
    legend.position = "none",
    axis.text = element_blank(),
    axis.title = element_blank(),
    panel.grid = element_blank(),
    plot.margin = unit(rep(-1,4), "cm") 
  ) +
  coord_polar() +  

 geom_text(data=label_data, aes(x=id, y=tot+10, label=individual, hjust=hjust), color="black", fontface="bold",alpha=0.6, size=5, angle= label_data$angle, inherit.aes = FALSE ) +

 geom_segment(data=base_data, aes(x = start, y = -5, xend = end, yend = -5), colour = "black", alpha=0.8, size=0.6 , inherit.aes = FALSE )  +

  geom_text(data=base_data, aes(x = title, y = -18, label=group), hjust=c(1,1,0,0), colour = "black", alpha=0.8, size=4, fontface="bold", inherit.aes = FALSE) 

 **ggsave(p, file="output1.png", width=10, height=10)**

我将不胜感激。

谢谢!!

个人群体价值1价值2价值3价值4

Biomarker1 Group1 0 1 2 2 Biomarker2 Group2 0 1 0 2 Biomarker3 Group2 0 1 0 1 Biomarker4 Group3 1 2 1 0 Biomarker5 Group4 0 2 4 1 Biomarker6 Group4 0 1 0 1 Biomarker7 Group4 0 1 0 1 Biomarker8 Group5 0 1 0 1 Biomarker9 Group6 0 1 1 1 Biomarker10 Group6 0 2 1 1

【问题讨论】:

  • 您是否使用了该帖子中的相同模拟数据?
  • 您好!如果你们(a)缩小问题范围并且(b)使您的示例可重现,我们可以为您提供更好的帮助。对于 (a),注释掉情节中的所有 geoms。然后一次通过 1 取消注释它们并运行绘图代码,直到找到错误。由于您的错误提到“位置堆栈”,它可能是geom_bar 行......然后,对于(b),您为我们没有的数据共享了大约 20 行数据操作代码。在绘制数据之前你对数据做了什么并不重要——重要的是你试图绘制的数据......
  • 因此,当您确定是哪一行导致错误时,请与我们分享这些数据。共享数据的最佳方式是使用dput(),因为它是可复制/可粘贴的。如果问题是您的geom_bar 行,它使用data(不是base_datalabel_datagrid_data),请在控制台中输入dput(data[1:20, ]) 并将结果编辑到您的问题中。这将是我们测试解决方案的前 20 行。 (当然,如果前 20 行不能说明问题,请使用不同的子集。)
  • 而且,当您编辑时,您可以通过删除所有数据争吵等来缩短问题。这将使您的问题更加平易近人、更加集中,并且您将更快地获得帮助。
  • 你的代码在 R4.0.0 和 ggplot2 3.3.0 上为我工作

标签: r bar-chart polar-coordinates


【解决方案1】:

这是来自链接帖子的修改代码,用于生成圆形条形图,中心有角度组标签。

library(ggplot2)
library(viridis)
library(tidyverse)

# Create dataset
data <- data.frame(
  individual=paste( "Mister ", seq(1,60), sep=""),
  group=c( rep('Group A', 10), rep('Group B', 30), rep('Group C', 14), rep('Group D', 6)) ,
  value=sample( seq(10,100), 60, replace=T), stringsAsFactors = TRUE)

# Set a number of 'empty bar' to add at the end of each group
empty_bar <- 3
to_add <- data.frame( matrix(NA, empty_bar*nlevels(data$group), ncol(data)) )
colnames(to_add) <- colnames(data)
to_add$group <- rep(levels(data$group), each=empty_bar)
data <- rbind(data, to_add)
data <- data %>% arrange(group)
data$id <- seq(1, nrow(data))

# Get the name and the y position of each label
label_data <- data
number_of_bar <- nrow(label_data)
angle <- 90 - 360 * (label_data$id-0.5) /number_of_bar 
label_data$hjust <- ifelse( angle < -90, 1, 0)
label_data$angle <- ifelse(angle < -90, angle+180, angle)

# prepare a data frame for base lines
base_data <- data %>% 
  group_by(group) %>% 
  summarize(start=min(id), end=max(id) - empty_bar) %>% 
  rowwise() %>% 
  mutate(title=mean(c(start, end)))

这是为组标签创建角度的附加代码

angle <- 90 - 360 * (base_data$title-0.5)/number_of_bar  
base_data$angle <- ifelse(angle < -90, angle+180, angle)

# prepare a data frame for grid (scales)
grid_data <- base_data
grid_data$end <- grid_data$end[ c( nrow(grid_data), 1:nrow(grid_data)-1)] + 1
grid_data$start <- grid_data$start - 1
grid_data <- grid_data[-1,]

# Make the plot
ggplot(data, aes(x=as.factor(id), y=value, fill=group)) +       # Note that id is a factor. If x is numeric, there is some space between the first bar

  geom_bar(aes(x=as.factor(id), y=value, fill=group), stat="identity", alpha=0.5) +

# Add a val=100/75/50/25 lines. I do it at the beginning to make sur barplots are OVER it.
  geom_segment(data=grid_data, aes(x = end, y = 80, xend = start, yend = 80), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_data, aes(x = end, y = 60, xend = start, yend = 60), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_data, aes(x = end, y = 40, xend = start, yend = 40), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +
  geom_segment(data=grid_data, aes(x = end, y = 20, xend = start, yend = 20), colour = "grey", alpha=1, size=0.3 , inherit.aes = FALSE ) +

  # Add text showing the value of each 100/75/50/25 lines
  annotate("text", x = rep(max(data$id),4), y = c(20, 40, 60, 80), label = c("20", "40", "60", "80") , color="grey", size=3 , angle=0, fontface="bold", hjust=1) +

  geom_bar(aes(x=as.factor(id), y=value, fill=group), stat="identity", alpha=0.5) +
  ylim(-50,120) +
  theme_minimal() +
  theme(
    legend.position = "none",
    axis.text = element_blank(),
    axis.title = element_blank(),
    panel.grid = element_blank(),
#    plot.margin = unit(rep(-1,4), "cm") 
  ) +

  coord_polar() + 
  geom_text(data=label_data, aes(x=id, y=value+10, label=individual, hjust=hjust), color="black", fontface="bold",alpha=0.6, size=2.5, angle= label_data$angle, inherit.aes = FALSE ) +

# Add base line information
geom_segment(data=base_data, aes(x = start, y = -1, xend = end, yend = -1), colour = "black", alpha=0.6, size=0.8, inherit.aes = F ) +

这里我们利用角度:

  geom_text(data=base_data, aes(x = title, y = -6, label=group, angle=angle), 
            hjust=c(1,1,0,0), colour = "black", alpha=0.7, size=2, fontface="bold", inherit.aes = FALSE)

【讨论】:

    【解决方案2】:

    这里有很多问题。前两个是严肃的并且关注“hard_coding”的使用。也就是说,代码不依赖于数据。后两个是您的数据而不是代码的小问题。

    1. hjust 参数:geom_text(data=base_data, aes(...), hjust=c(1,1,0,0), ...
    2. y 轴范围:ylim(-150, max(label_data$tot, na.rm=T))
    3. 数据高度偏斜。
    4. 您的酒吧和群组太多。

    数字 1 导致错误:

    # Error: Aesthetics must be either length 1 or the same as the data (24): hjust
    # Run `rlang::last_error()` to see where the error occurred.
    

    在链接的帖子中,base_data 如下所示:

    # A tibble: 4 x 4
      group start   end title
      <chr> <int> <dbl> <dbl>
    1 A         1     8   4.5
    2 B        11    38  24.5
    3 C        41    52  46.5
    4 D        55    58  56.5
    

    但是对于您的数据,它看起来像这样:

    # A tibble: 24 x 4
       group   start   end title
       <chr>   <int> <dbl> <dbl>
     1 Group1      1    -1   0  
     2 Group10     2     1   1.5
     3 Group11     4     5   4.5
     4 Group12     8     8   8  
     5 Group13    11     9  10  
     6 Group14    12    42  27  
     7 Group15    45    43  44  
     8 Group16    46    47  46.5
     9 Group17    50    49  49.5
    10 Group18    52    52  52  
    # ... with 14 more rows
    

    因此,hjust 参数需要更改为取决于数据的内容,而不是使用值进行硬编码。也许只是省略它,看看图表是什么样子,如果需要的话可以改变它。

    数字 2 并不严重,但会导致您的图表在中心出现一个大洞。 -150 的值是基于数据的,所以这(硬编码)是不好的做法。看起来最小 y 轴值应该更改为 -max(label_data$tot, na.rm=T),现在更通用了。但这可能需要一些修补才能获得最佳结果。理想值也可能取决于条形的数量和数据的偏度。

    还有其他部分也使用了硬编码。

    数字 3 并不严重,但会导致一些标签出现在绘图区域之外。您可以尝试转换 y 轴,但我会让您自己决定。

    数字4也不严重,但会导致内圈内的标签重叠。

    修复这些和其他小问题后,您应该得到以下结果:


    【讨论】:

    • 嗨@Edward,我让它工作了。这非常有帮助,非常感谢。你知道是否可以改变条的颜色吗?例如,我想将黄色变为绿色,将绿色变为橙色......等等。
    • 第三行:scale_fill_viridis() 确定颜色。
    • 对,只需要将第三行替换为:withscale_fill_manual(values = c("black", "grey")
    • 嗨@Edward - 我想知道您是否认为我能够调整内部文本(组)以与生物标记的外部文本对齐?
    • 应该可以的。
    猜你喜欢
    • 1970-01-01
    • 2017-11-04
    • 2022-06-29
    • 1970-01-01
    • 1970-01-01
    • 2021-10-17
    • 2016-10-13
    • 2022-08-20
    • 1970-01-01
    相关资源
    最近更新 更多