ggplot2 热图,平铺高度和宽度为 aes()

问题描述

我正在尝试为 OD 矩阵创建热图,但我想按特定权重缩放行和列。由于这些权重在每个类别中都是恒定的,我希望该图会保持行和列的结构。

# Tidy OD matrix
df <- data.frame (origin  = c(rep("A",3),rep("B",rep("C",3)),destination = rep(c("A","B","C"),value = c(0,1,10,5,11,15,6,0))

# Weights
wdf <- data.frame(region = c("A",w = c(1,2,3))

# Add weights to the data.
plot_df <- df %>% 
  merge(wdf %>% rename(w_origin = w),by.x = 'origin',by.y = 'region') %>% 
  merge(wdf %>% rename(w_destination = w),by.x = 'destination',by.y = 'region')
  

数据如下所示:

> plot_df
  destination origin value w_origin w_destination
1           A      A     0        1             1
2           A      C    15        3             1
3           A      B     5        2             1
4           B      A     1        1             2
5           B      B     0        2             2
6           B      C     6        3             2
7           C      B    11        2             3
8           C      A    10        1             3
9           C      C     0        3             3

但是,当在 width 中将权重作为 heightaes() 传递时,我得到了:

ggplot(plot_df,aes(x = destination,y = origin)) +
  geom_tile(
    aes(
      width = w_destination,height = w_origin,fill = value),color = 'black')

enter image description here

它似乎适用于列的大小(宽度),但不完全是因为比例不正确。而且这些行到处都是,没有对齐。

我只使用 geom_tile 是因为我可以通过 heightwidth 作为美学,但我接受其他建议。

解决方法

所以我想我为您提供了部分解决方案。在使用了 geom_tile 之后,当您使用高度和宽度时,数据框的顺序似乎很重要。

这是我想出的一些示例代码(先运行你的代码)。我将您的 data_frame 转换为 tibble(dplyr 的一部分),以便更轻松地按列排序。

# Converted your dataframe to a tibble dataframe
plot_df_tibble = tibble(plot_df)

# Sorted your dataframe by your w_origin column:
plot_df_tibble2 = plot_df_tibble[order(plot_df_tibble$w_origin),]

# Plotted the sorted data frame:
ggplot(plot_df_tibble2,aes(x = destination,y = origin)) +
  geom_tile(
    aes(
      width = w_destination,height = w_origin,fill = value),color = 'black')

得到这个情节: Link to image I made

我应该注意,如果您在排序之前运行转换后的 tibble,您会得到与您发布的相同的图。

对于 geom_tile 的这一部分,似乎高度和宽度的争论可能没有完全发展,因为我觉得 df 的顺序应该无关紧要。 干杯

,

问题在于您的图块重叠。原因是虽然您可以将宽度和高度作为美学传递,但 geom_tile 不会为您调整瓷砖的 x 和 y 位置。当您在 x 和 y 上映射离散变量时,您的瓷砖位于等距网格上。在您的情况下,图块位于 0.5、1.5 和 2.5。然后以指定的宽度和高度在这些位置绘制图块。

通过为您的绘图添加一些透明度可以很容易地看到这一点:

library(ggplot2)
library(dplyr)

ggplot(plot_df,color = "black",alpha = .2)

要获得所需的结果,您必须根据所需的宽度和高度手动计算 x 和 y 位置,以防止框重叠。为此,您可以切换到连续比例并通过 scale_x/y_ continuous:

设置所需的中断和标签
breaks <- wdf %>% 
  mutate(cumw = cumsum(w),pos = .5 * (cumw + lag(cumw,default = 0))) %>% 
  select(region,pos)

plot_df <- plot_df %>% 
  left_join(breaks,by = c("origin" = "region")) %>% 
  rename(y = pos) %>% 
  left_join(breaks,by = c("destination" = "region")) %>% 
  rename(x = pos)

ggplot(plot_df,aes(x = x,y = y)) +
  geom_tile(
    aes(
      width = w_destination,color = "black") +
  scale_x_continuous(breaks = breaks$pos,labels = breaks$region,expand = c(0,0.1)) +
  scale_y_continuous(breaks = breaks$pos,0.1))