【问题标题】:ggplot2 heatmap with tile height and width as aes()ggplot2 热图,平铺高度和宽度为 aes()
【发布时间】:2021-07-03 21:17:38
【问题描述】:

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

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

# Weights
wdf <- data.frame(region = c("A","B","C"),
                  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

但是,当在aes() 中将权重作为widthheight 传递时,我得到了这个:

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

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

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

【问题讨论】:

    标签: r ggplot2 heatmap aesthetics


    【解决方案1】:

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

    这是我从您那里提出的一些示例代码(首先运行您的代码)。我将您的 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 的顺序应该无关紧要。 干杯

    【讨论】:

      【解决方案2】:

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

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

      library(ggplot2)
      library(dplyr)
      
      ggplot(plot_df, 
             aes(x = destination, 
                 y = origin)) +
        geom_tile(
          aes(
            width = w_destination,
            height = w_origin,
            fill = value), 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,
            height = w_origin,
            fill = value), color = "black") +
        scale_x_continuous(breaks = breaks$pos, labels = breaks$region, expand = c(0, 0.1)) +
        scale_y_continuous(breaks = breaks$pos, labels = breaks$region, expand = c(0, 0.1))
      

      【讨论】:

      • 太棒了!这解释了它并且运作良好。谢谢!
      • 我不确定我是否理解 pos = .5 * (cumw + lag(cumw, default = 0)) 中发生的事情。当我尝试使用其他(更大的)值时,它不起作用。你能解释一下吗?谢谢
      • 通过累积,我们得到一个向量,其上界为cumw,而lag(cumw, default = 0) 给出下界。然而,geom_tile 需要中点来放置图块,这正是pos = .5 * (cumw + lag(cumw, default = 0)) 正在做的事情。为您采样数据cumw = c(1, 3, 6)lag(...) = c(0, 1, 3)pos = c(.5, 2, 4.5)。不知道出了什么问题。我的第一个猜测是数据顺序出了问题。但我刚刚检查过,它仍然可以正常工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-26
      • 2011-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多