R 中的圆形堆积条形图 - 美学必须是长度 1 或与数据相同 (26)
Circular stacked barplot in R - Aesthetics must be either length 1 or the same as the data (26)
我正在尝试创建一个圆形堆叠条形图,如此处所述 (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)**
如有任何帮助,我将不胜感激。
谢谢!!
个人组value1 value2 value3 value4
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
这里有很多问题。前两个是严肃的,涉及 "hard_coding" 的使用。也就是说,代码不依赖于数据。后两个是您的数据的小问题,而不是代码。
hjust
参数:geom_text(data=base_data, aes(...), hjust=c(1,1,0,0), ...
- y 轴范围:
ylim(-150, max(label_data$tot, na.rm=T))
- 数据严重偏斜。
- 你有太多的酒吧和太多的组。
数字 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.
在链接的 post 中,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号也不严重,但导致内圈内的标签重叠。
解决这些问题和其他小问题后,您应该得到以下结果:
这是来自链接 post 的修改代码,用于生成一个圆形条形图,中间有角度组标签。
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)
我正在尝试创建一个圆形堆叠条形图,如此处所述 (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)**
如有任何帮助,我将不胜感激。
谢谢!!
个人组value1 value2 value3 value4
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
这里有很多问题。前两个是严肃的,涉及 "hard_coding" 的使用。也就是说,代码不依赖于数据。后两个是您的数据的小问题,而不是代码。
hjust
参数:geom_text(data=base_data, aes(...), hjust=c(1,1,0,0), ...
- y 轴范围:
ylim(-150, max(label_data$tot, na.rm=T))
- 数据严重偏斜。
- 你有太多的酒吧和太多的组。
数字 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.
在链接的 post 中,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号也不严重,但导致内圈内的标签重叠。
解决这些问题和其他小问题后,您应该得到以下结果:
这是来自链接 post 的修改代码,用于生成一个圆形条形图,中间有角度组标签。
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)