如何用两个特征双重填充 geom_bar

How to double fill a geom_bar with two characteristics

我正在处理房价指数,我对如何将另一个几何图形添加到 ggplot 有疑问。这是我为这个问题制作的示例数据。 我有来自人口普查和在线帖子的住房数据。 rooms 表示住房特征(很多或很少房间)的变量,value 是具有该特征的每个来源的房屋百分比。然后,houses and apts 显示城市拥有该数据源的房屋和公寓的百分比。因此,例如,城市 1 在人口普查数据中有 40% 的房屋和 60% 的公寓,在 zillow 数据中有 45% 的房屋和 55% 的公寓。 我按房间做了一个 geom_bar 分面并按来源填充,所以我有两个地块,一个用于房间 = 1,另一个用于房间 = 2,每个城市都有两个条形图(每个来源一个)。 现在,我想用每个城市和来源的房屋和公寓百分比填充这些相同的条。

如果有人能帮助我,我将不胜感激。

我目前用于绘图的代码如下:


df <- tibble::tribble(
  ~city, ~source, ~rooms, ~value, ~houses, ~apts,
  "city1", "census", "1", 0.8,  0.4,  0.6,
  "city1", "census", "2", 0.2,  0.4,  0.6,
  "city1", "zillow", "1", 0.7,  0.45, 0.55,
  "city1", "zillow", "2", 0.3,  0.45, 0.55,
  "city2", "census", "1", 0.74, 0.66, 0.34,
  "city2", "census", "2", 0.26, 0.66, 0.34,
  "city2", "zillow", "1", 0.37, 0.66, 0.34,
  "city2", "zillow", "2", 0.63, 0.66, 0.34,
  "city3", "census", "1", 0.81, 0.71, 0.29,
  "city3", "census", "2", 0.19, 0.71, 0.29,
  "city3", "zillow", "1", 0.49, 0.71, 0.29,
  "city3", "zillow", "2", 0.51, 0.71, 0.29)

ggplot(df, aes(fill=source, y=city, x=value)) + 
  geom_bar(position = "dodge", stat = "identity") +
  facet_wrap(facets="rooms", nrow=2) 

如果我没理解错的话,您希望在一个图中分离并显示以下差异:

  • 城市
  • 房间
  • 值(此处柱的长度)
  • % houses 或 % apts(一个是另一个的倒数,所以基本上只是显示相同的东西)

如果我猜对了,也许最简单的方法是使用 facet_grid():

对两个变量而不是一个变量进行分面
ggplot(df, aes(fill=houses, y=city, x=value)) +
  geom_col(position='dodge') +
  facet_grid(source ~ rooms)

另一种方法可能是使用另一种美学来分离您的 source 列(而不是将其作为一个方面),并仍然保持 fill 美学映射到房屋的百分比:

ggplot(df, aes(fill=houses, y=city, x=value)) +
  geom_col(
    position=position_dodge(width=0.8), width=0.7, size=1, color='black',
    aes(linetype=source)
  ) +
  facet_wrap(~rooms, nrow=2)

这种方式可行,但看起来不太好。如果您这样做,我会修改一些主题元素并向条形添加一些 alpha 值以使内容更易于查看。 alpha 不会转化为图例,因此您实际上也需要对其进行修改......好吧......这是最终产品和代码。

ggplot(df, aes(fill=houses, y=city, x=value)) +
  geom_col(
    position=position_dodge(width=0.8), width=0.7, size=1,
    color='black', alpha=0.4,
    aes(linetype=source, alpha=source)
  ) +
  
  scale_fill_distiller(palette='RdYlBu') +
  guides(
    linetype=guide_legend(override.aes = list(fill=NA))
  ) +
  
  facet_wrap(~rooms, nrow=2) +
  
  theme_classic() +
  theme(
    panel.spacing = unit(0.08, 'npc')
  )

你可能明白了。不过请注意一些事项:

  • 我这里用的是geom_col(),建议不要用geom_bar(stat='identity')。请注意建议此用法的 documentation

  • 建议使用position=position_dodge()代替position="dodge"。这使您可以调整闪避列之间的距离,如果您还想调整条形的宽度,则这一点尤其重要。我想这样做是为了更容易看到条形线。

其中还隐藏了一些其他技巧,但希望这对您有所帮助,您可以 select 从类似的东西中解决您的问题。