如何在ggplot2的条形图中添加第三个变量?

How to add 3rd variable in bar chart for ggplot2?

我正在尝试制作一个带有第三个变量(在本例中为“频率”)的条形图,其中第三个变量会改变条形的宽度(更高的频率 = 更大的宽度)。显然我必须弄清楚尺寸,但这只是美学,我可以稍后再弄清楚。当我使用此代码时,我不断收到错误消息“position_dodge 需要非重叠 x 间隔”,然后绘图会堆叠条形而不是对它们进行分组。另外(也许这会有所帮助)想知道是否有办法增加 x 轴上标签之间的距离(意味着增加“Iso”、“Transition”、“P&R Handler”等之间的距离) 感谢所有帮助。

library(tidyverse)
library(ggrepel)
percentile_playtype = c(70.10, 41.20, 83.90, 0, 0, 97.30, 40, 0, 49.30, 20.10, 88.90, 91.80,
                        94.60, 0, 83.60, 86.90, 42, 41.10, 46.90, 0, 81.50, 84.00)
frequency = c(8.5,16.5,53.3,0,0,6,7.2,0,2.1,0.6,5.4,1.9,12.4,0,28,8.1,16,1.9,13.6,0,10.6,6.1)
v1 = sqrt(sqrt(sqrt(frequency)))/10
lowsize <- element_text(size=8)
playtype = c("Iso","Transition","P&R Handler","P&R Roll","Post Up","Spot Up",
             "Handoff","Cut","Off Screen","Putbacks","Misc")
Player = rep(c("Trae Young","John Collins"), each=11)
PlayData <- data.frame(percentile_playtype,frequency,playtype,Player)
a1 <- ggplot(PlayData, aes(fill=Player, y=percentile_playtype, x=playtype)) + 
  geom_bar(position="dodge", stat="identity",width=v1)
a1

您是否在尝试模仿马赛克图之类的东西?

percentile_playtype = c(70.10, 41.20, 83.90, 0, 0, 97.30, 40, 0, 49.30, 20.10, 88.90, 91.80,
                        94.60, 0, 83.60, 86.90, 42, 41.10, 46.90, 0, 81.50, 84.00)
frequency = c(8.5,16.5,53.3,0,0,6,7.2,0,2.1,0.6,5.4,1.9,12.4,0,28,8.1,16,1.9,13.6,0,10.6,6.1)
v1 = sqrt(sqrt(sqrt(frequency)))/10
playtype = c("Iso","Transition","P&R Handler","P&R Roll","Post Up","Spot Up",
             "Handoff","Cut","Off Screen","Putbacks","Misc")
Player = rep(c("Trae Young","John Collins"), each=11)
PlayData <- data.frame(percentile_playtype,frequency,playtype,Player)

CGPfunctions::PlotXTabs2(PlayData, 
                         x = playtype, 
                         y = Player, 
                         counts = percentile_playtype, 
                         plottype = "mosaic", 
                         x.axis.orientation = "slant",
                         sample.size.label = FALSE,
                         label.text.size = 2)

如果你真的想将频率映射到条形宽度,你需要用困难的方式来做,并计算那些宽度,绘制 geom_rect 而不是 geom_bar。从视觉效果的角度来看,最好缩放条形的 区域 而不是它们的绝对宽度:

PlayData$playtype_n <- as.numeric(as.factor(PlayData$playtype))
PlayData$frequency_n <- PlayData$frequency/max(PlayData$frequency) * 0.5 / 
                        (PlayData$percentile_playtype / 100) *
                        (2 * as.numeric(as.factor(PlayData$Player)) - 3) +
                        as.numeric(as.factor(PlayData$playtype))


ggplot(PlayData, aes(fill = Player)) + 
  geom_rect(aes(xmin = playtype_n, xmax = frequency_n, ymin = 0,
                ymax = percentile_playtype)) +
  scale_x_continuous(breaks = sort(unique(PlayData$playtype_n)),
                     labels = levels(as.factor(PlayData$playtype))) +
  scale_fill_manual(values = c("deepskyblue4", "orange")) +
  labs(x = "Play type (area scaled to frequency)", y = "Percentile playtype") +
  theme_bw()

就我个人而言,我认为这看起来不太好,而且我不认为这值得麻烦。另一种更容易理解的方法可能是使用 facets

ggplot(PlayData, aes(fill=frequency, y=percentile_playtype, x=playtype)) + 
  geom_col(position = "dodge", width=0.75) +
  geom_text(aes(label = frequency), vjust = 1.5, color = "white") +
  facet_wrap(Player~., ncol = 1) +
  scale_fill_viridis_c() +
  theme_classic() +
  theme(panel.grid.major.y = element_line(color = "gray90"),
        strip.background = element_blank(),
        strip.text.x = element_text(size = 16),
        axis.line.x.bottom = element_line())

或者可能是使用 ggrepel 的标记散点图:

ggplot(PlayData, aes(percentile_playtype, frequency, color = Player)) +
  geom_point() +
  geom_text_repel(aes(label = playtype), size = 5) +
  scale_color_manual(values = c("deepskyblue4", "orange")) +
  theme_bw()