我正在尝试使用 ggplot2 创建圆形、堆叠和分组条形图。我遇到的问题是
我的数据如下所示:
structure(list(`No of Carbon` = c(9, 9, 10, 8, 6, 4, 8, 9, 8,
8, 13, 4, 6, 10, 6, 7, 6, 5, 5, 8, 11, 6, 2, 9, 8, 4, 14, 12,
4, 4, 10, 6, 6, 9, 10, 9, 10, 4, 8, 6), `Functional Group` = c("Carboxylate",
"Carboxylate", "Carboxylate", "Sulfonate", "Carboxylate", "Sulfonate",
"Carboxylate", "Carboxylate", "Carboxylate", "Sulfonate", "Carboxylate",
"Carboxylate", "Sulfonate", "Sulfonate", "Sulfonate", "Carboxylate",
"Carboxylate", "Carboxylate", "Carboxylate", "Sulfonate", "Carboxylate",
"Sulfonate", "Carboxylate", "Carboxylate", "Carboxylate", "Sulfonate",
"Carboxylate", "Carboxylate", "Carboxylate", "Carboxylate", "Sulfonate",
"Sulfonate", "Carboxylate", "Carboxylate", "Sulfonate", "Carboxylate",
"Carboxylate", "Sulfonate", "Carboxylate", "Sulfonate"), `PFAS Type` = structure(c(28L,
28L, 20L, 4L, 26L, 19L, 30L, 28L, 30L, 33L, 41L, 18L, 27L, 7L,
27L, 24L, 26L, 37L, 37L, 33L, 17L, 27L, 36L, 28L, 30L, 19L, 40L,
22L, 18L, 18L, 6L, 27L, 14L, 28L, 23L, 28L, 20L, 19L, 30L, 27L
), levels = c("4:2 Cl-PFESA", "4:2 FTS", "6:2 Cl-PFESA", "6:2 FTS",
"6:2 H-PFESA", "8:2 Cl-PFESA", "8:2 FTS", "ADONA", "FBSA", "FHxSA",
"FOSA", "FOSAA", "GenX", "HFPO-DA", "HFPO-TA", "N-Et-FOSAA",
"N-Me-FOSAA", "PFBA", "PFBS", "PFDA", "PFDDA", "PFDoA", "PFDS",
"PFHpA", "PFHpS", "PFHxA", "PFHxS", "PFNA", "PFNS", "PFOA", "PFONDS",
"PFONS", "PFOS", "PFOSA", "PFOUDS", "PFPA", "PFPeA", "PFPeS",
"PFTDA", "PFTeDA", "PFTrDA", "PFUA", "PFUdA", "PFUnA"), class = "factor"),
concentrations = c(0.45, 5.9, 0.83, 1.2, 0.82, 2.04, 12.7,
1.15, 2.71, 156, 0.71, 5.37, 0.00007, 0.04, 0.35, 0.19, 2.95,
0.26, 2.63, 0.96, 0.33, 117.18, 16, 0.4, 24, 0.45, 1.33,
3.57, 3.6, 3.15, 0.02, 0.97, 1.38, 0.34, 0.22, 1.34, 3.3,
5.27, 3.69, 3.54), carbon_chain = c("Long Chain PFAS", "Long Chain PFAS",
"Long Chain PFAS", "Short Chain PFAS", "Short Chain PFAS",
"Short Chain PFAS", "Short Chain PFAS", "Long Chain PFAS",
"Short Chain PFAS", "Short Chain PFAS", "Long Chain PFAS",
"Short Chain PFAS", "Short Chain PFAS", "Long Chain PFAS",
"Short Chain PFAS", "Short Chain PFAS", "Short Chain PFAS",
"Short Chain PFAS", "Short Chain PFAS", "Short Chain PFAS",
"Long Chain PFAS", "Short Chain PFAS", "Short Chain PFAS",
"Long Chain PFAS", "Short Chain PFAS", "Short Chain PFAS",
"Long Chain PFAS", "Long Chain PFAS", "Short Chain PFAS",
"Short Chain PFAS", "Long Chain PFAS", "Short Chain PFAS",
"Short Chain PFAS", "Long Chain PFAS", "Long Chain PFAS",
"Long Chain PFAS", "Long Chain PFAS", "Short Chain PFAS",
"Short Chain PFAS", "Short Chain PFAS"), group = structure(c(3L,
3L, 3L, 3L, 3L, 3L, 2L, 3L, 3L, 2L, 3L, 3L, 1L, 3L, 2L, 1L,
3L, 1L, 3L, 3L, 3L, 2L, 2L, 1L, 2L, 3L, 3L, 3L, 3L, 3L, 3L,
3L, 3L, 3L, 3L, 3L, 2L, 3L, 3L, 3L), levels = c("rain", "stormwater",
"surface"), class = "factor")), row.names = c(NA, -40L), na.action = structure(c(`7` = 7L,
`8` = 8L, `9` = 9L, `10` = 10L, `11` = 11L, `12` = 12L, `13` = 13L,
`14` = 14L, `15` = 15L, `16` = 16L, `17` = 17L, `18` = 18L, `19` = 19L,
`20` = 20L, `21` = 21L, `22` = 22L, `42` = 42L, `43` = 43L, `44` = 44L,
`59` = 59L, `60` = 60L, `61` = 61L, `62` = 62L, `63` = 63L, `64` = 64L,
`65` = 65L, `66` = 66L, `76` = 76L, `77` = 77L, `78` = 78L, `79` = 79L,
`80` = 80L, `81` = 81L, `82` = 82L, `83` = 83L, `84` = 84L, `85` = 85L,
`86` = 86L, `87` = 87L, `88` = 88L, `94` = 94L, `95` = 95L, `96` = 96L,
`97` = 97L, `98` = 98L, `99` = 99L, `100` = 100L, `101` = 101L,
`102` = 102L, `103` = 103L, `104` = 104L, `105` = 105L, `106` = 106L,
`107` = 107L, `108` = 108L, `109` = 109L, `110` = 110L, `136` = 136L,
`137` = 137L, `138` = 138L, `139` = 139L, `140` = 140L, `141` = 141L,
`142` = 142L, `143` = 143L, `144` = 144L, `145` = 145L, `146` = 146L,
`147` = 147L, `148` = 148L, `149` = 149L, `150` = 150L, `151` = 151L,
`152` = 152L, `153` = 153L, `154` = 154L, `157` = 157L, `158` = 158L,
`159` = 159L, `160` = 160L, `161` = 161L, `162` = 162L, `163` = 163L,
`164` = 164L, `165` = 165L, `166` = 166L, `167` = 167L, `168` = 168L,
`169` = 169L, `170` = 170L, `171` = 171L, `172` = 172L, `173` = 173L,
`174` = 174L, `175` = 175L, `176` = 176L, `180` = 180L, `181` = 181L,
`182` = 182L, `183` = 183L, `184` = 184L, `185` = 185L, `186` = 186L,
`187` = 187L, `188` = 188L, `189` = 189L, `190` = 190L, `191` = 191L,
`192` = 192L, `193` = 193L, `194` = 194L, `195` = 195L, `196` = 196L,
`197` = 197L, `198` = 198L, `200` = 200L, `201` = 201L, `202` = 202L,
`203` = 203L, `204` = 204L, `205` = 205L, `206` = 206L, `207` = 207L,
`208` = 208L, `209` = 209L, `210` = 210L, `211` = 211L, `212` = 212L,
`213` = 213L, `214` = 214L, `215` = 215L, `216` = 216L, `217` = 217L,
`218` = 218L, `219` = 219L, `220` = 220L, `224` = 224L, `225` = 225L,
`226` = 226L, `227` = 227L, `228` = 228L, `229` = 229L, `230` = 230L,
`231` = 231L, `232` = 232L, `233` = 233L, `234` = 234L, `235` = 235L,
`236` = 236L, `237` = 237L, `238` = 238L, `239` = 239L, `240` = 240L,
`241` = 241L, `242` = 242L, `248` = 248L, `249` = 249L, `250` = 250L,
`251` = 251L, `252` = 252L, `253` = 253L, `254` = 254L, `255` = 255L,
`256` = 256L, `257` = 257L, `258` = 258L, `259` = 259L, `260` = 260L,
`261` = 261L, `262` = 262L, `263` = 263L, `264` = 264L, `270` = 270L,
`271` = 271L, `272` = 272L, `273` = 273L, `274` = 274L, `275` = 275L,
`276` = 276L, `277` = 277L, `278` = 278L, `279` = 279L, `280` = 280L,
`281` = 281L, `282` = 282L, `283` = 283L, `284` = 284L, `285` = 285L,
`286` = 286L, `290` = 290L, `291` = 291L, `292` = 292L, `293` = 293L,
`294` = 294L, `295` = 295L, `296` = 296L, `297` = 297L, `298` = 298L,
`299` = 299L, `300` = 300L, `301` = 301L, `302` = 302L, `303` = 303L,
`304` = 304L, `305` = 305L, `306` = 306L, `307` = 307L, `308` = 308L,
`311` = 311L, `312` = 312L, `313` = 313L, `314` = 314L, `315` = 315L,
`316` = 316L, `317` = 317L, `318` = 318L, `319` = 319L, `320` = 320L,
`321` = 321L, `322` = 322L, `323` = 323L, `324` = 324L, `325` = 325L,
`326` = 326L, `327` = 327L, `328` = 328L, `329` = 329L, `330` = 330L,
`333` = 333L, `334` = 334L, `335` = 335L, `336` = 336L, `337` = 337L,
`338` = 338L, `339` = 339L, `340` = 340L, `341` = 341L, `342` = 342L,
`343` = 343L, `344` = 344L, `345` = 345L, `346` = 346L, `347` = 347L,
`348` = 348L, `349` = 349L, `350` = 350L, `351` = 351L, `352` = 352L,
`355` = 355L, `356` = 356L, `357` = 357L, `358` = 358L, `359` = 359L,
`360` = 360L, `361` = 361L, `362` = 362L, `363` = 363L, `364` = 364L,
`365` = 365L, `366` = 366L, `367` = 367L, `368` = 368L, `369` = 369L,
`370` = 370L, `371` = 371L, `372` = 372L, `373` = 373L, `374` = 374L
), class = "omit"), class = c("tbl_df", "tbl", "data.frame"))
这就是我目前所做的:
df %>%
summarise(N = n(), .by = c(group, carbon_chain, `Functional Group`)) |>
arrange(desc(`Functional Group`), carbon_chain, group) |>
mutate(
prop = N / sum(N),
label_y = cumsum(prop),
x = paste0(group, "\n", carbon_chain),
.by = c(group, carbon_chain)
) %>%
ggplot(aes(x = x, y = prop, fill = `Functional Group`)) +
geom_col(position = "fill", color = "black") +
geom_label(aes(y = label_y, label = scales::percent(prop, 1)), fill = "white",
show.legend = F, position = position_fill(vjust = 0.5), size = 2) +
coord_polar() +
ylim(c(-1, NA)) + # hole size
labs(x = NULL, y = NULL) +
theme_minimal() +
theme(
panel.grid.major.y = element_line(color = "gray", linetype = "dotted"),
axis.text.y = element_blank(),
legend.position = "bottom"
)
所以你可以看到道具标签没有以各自的部分为中心,并且外部标签看起来很混乱。我正在考虑将这些当前外部标签放在内部并且不重复。因此,标签的一个内层将是“雨”、“地表”和“暴雨”,每个标签将覆盖两个“条”。第二个内部标签将涵盖长链和短链
正如 @teunbrand 在评论中已经提到的,您可以通过将
prop
映射到 y
并使用 position_stack
来解决第一个问题。对于第二个问题,您可以按照 R 图库中的示例,首先创建一个数据框来绘制内圆的线段,其中我使用 geom_segment
代替 geom_text
和 geomtextpath::geom_textsegment
,它允许绘制线段和文本一次完成,并允许弯曲文本。此外,我切换到 geomtextpath::coord_curvedpolar()
,它允许弯曲的 x 轴文本标签,对于后者,我将信息放在组上,因为这现在反映在内圈中。如果您希望将轴文本作为第二个内圆,您可以遵循我用于第一个内圆的方法。
library(dplyr, warn = FALSE)
library(ggplot2)
library(geomtextpath)
# prepare a data frame for base lines
base_data <- df %>%
distinct(group, carbon_chain) %>%
arrange(group, carbon_chain) |>
mutate(id = row_number()) |>
summarise(
start = min(id) - .4,
end = max(id) + .4,
.by = group
) |>
mutate(title = rowMeans(across(c(start, end))))
df %>%
summarise(N = n(), .by = c(group, carbon_chain, `Functional Group`)) |>
arrange(desc(`Functional Group`), carbon_chain, group) |>
mutate(
prop = N / sum(N),
x = paste0(group, "_", carbon_chain),
.by = c(group, carbon_chain)
) %>%
ggplot(aes(x = x, y = prop, fill = `Functional Group`)) +
geom_col(position = "fill", color = "black") +
geom_label(
aes(y = prop, label = scales::percent(prop, 1)),
fill = "white",
show.legend = FALSE,
position = position_stack(vjust = 0.5),
size = 8 / .pt
) +
# Add base line information
geomtextpath::geom_textsegment(
data = base_data,
aes(
x = start, y = -.1,
xend = end, yend = -.1,
label = group
),
colour = "black",
linewidth = 0.6,
size = 8 / .pt,
inherit.aes = FALSE,
gap = FALSE,
offset = unit(-8, "pt")
) +
scale_x_discrete(
labels = ~ gsub("^.*?_", "", .x)
) +
geomtextpath::coord_curvedpolar() +
ylim(c(-1, NA)) + # hole size
labs(x = NULL, y = NULL) +
theme_minimal() +
theme(
panel.grid.major.y = element_line(color = "gray", linetype = "dotted"),
axis.text.y = element_blank(),
axis.text.x = element_text(vjust = .5),
legend.position = "bottom"
)