【问题标题】:Using geom_tile for heatmap将 geom_tile 用于热图
【发布时间】:2019-02-11 02:46:51
【问题描述】:

我整整两天一直在解决一个问题,但似乎无法正确解决。我想创建一个图表,显示我大学一天中的每个小时和一周中的每一天的教室使用情况,这样我们的教学经理就可以轻松了解哪些教室没有得到充分利用。

我必须使用的数据如下所示:

room strTime endTime days pctFill
1101 1345    1500    MW   91.67
1102 1345    1630    MW   95.83
1102 1730    2015    MW   66.67
1104 0915    1200    MW   62.50
1104 1345    1630    MW   45.83

df 中的每一行代表在一个房间里开会的一个班级。 “房间”是房间号。 "strTime" 和 "endTime" 是那个房间里上课的开始和结束时间。这些是文本字段,但可以轻松转换为时间或任何其他格式。 "days" 是一周中班级聚会的日子。我知道我必须划分“天”数据并相信为每一天创建一个新行是最简单的,因此第一行将分为两行:一个用于星期一,一个用于星期三。 “pctFill”是该房间的填充百分比(一个可容纳 20 名学生但包含 15 名学生的房间将是 75.00 pctFill)。

我想使用 geom_tile(或 geom_raster 或 geom_rect)创建一个热图类型的绘图。我设想该图将沿 x 轴显示一周中的几天,沿 y 轴显示一天中的时间,其中每个相交的块将填充代表教室填充百分比的颜色。我已经完成了几个教程并了解了 geom_tile 的概念,并且可以为 mtcars 创建一个非常棒的图。不幸的是,我认为我使用的数据似乎并没有以同样的方式工作,因为它是时间而不是简单的分类变量。我尝试使用所有三个几何图形创建一个绘图,但没有取得多大成功。我可以让 geom_tile 几乎可以工作,但是每个图块都以开始时间为中心,而不是开始时间框的下边缘。此外,这些框的高度都相同,这可能是由于 y 轴比例。我尝试使用 geom_raster 并创建一个 y 轴分为 15 分钟间隔的网格,然后用适当的颜色填充每个网格块。不幸的是,无论我在那个情节上做错了什么,都只产生了一个空网格。 geom_rect 可以工作,但我想不出一种方法来使矩形变宽,而不创建一个伪变量,每个房间值之间都有一个值。

这是我最接近可行的方法:

ggplot() +
  geom_tile(
    data = df
    ,mapping = aes(x = room
                   ,y = strTime
                   ,fill = pctFill
                   )
    ,color = 'white'
    ,alpha = 0.5
    ) +
  scale_fill_gradient(low = 'white', high = 'steelblue')

如果有人有与我正在做的类似的示例图并且不介意分享该图的代码,我将不胜感激。或者,只需指向正确方向的指针就足够了。感谢您提供的任何帮助。

【问题讨论】:

    标签: r ggplot2 heatmap


    【解决方案1】:

    这样的事情怎么样?

    首先,您的示例数据:

    library(tidyverse)
    txt <- 'room strTime endTime days pctFill
    1101 1345    1500    MW   91.67
    1102 1345    1630    MW   95.83
    1102 1730    2015    MW   66.67
    1104 0915    1200    MW   62.50
    1104 1345    1630    MW   45.83'
    
    df <- read.table(text = txt, header = T)
    

    然后,我们转换数据,使一周中的每一天都在自己的行中:

    df <- read.table(text = txt, header = T) %>% 
      mutate(days = str_split(days, '')) %>% 
      unnest(days)
    
       room strTime endTime pctFill days
    1  1101    1345    1500   91.67    M
    2  1101    1345    1500   91.67    W
    3  1102    1345    1630   95.83    M
    4  1102    1345    1630   95.83    W
    5  1102    1730    2015   66.67    M
    6  1102    1730    2015   66.67    W
    7  1104     915    1200   62.50    M
    8  1104     915    1200   62.50    W
    9  1104    1345    1630   45.83    M
    10 1104    1345    1630   45.83    W
    

    最后,一个使用geom_rect()的情节:

    plot.rooms <- ggplot(data = df, aes(xmin = room - 0.33, xmax = room + 0.33,  ymin = strTime, ymax = endTime)) +
      geom_rect(aes(alpha = pctFill)) +
      facet_grid(facets = ~days) +
      scale_x_continuous(breaks = sort(unique(df$room))) +
      scale_alpha_continuous(range = c(0.3, 1))
    print(plot.rooms)
    

    【讨论】:

    • 我很尴尬——这是一个如此简单的解决方案。我不敢相信我为此工作了整整两天,自己却没有找到这个解决方案。关键似乎在于正确格式化输入数据,但我担心如何设置 ggplot!感谢您的帮助。
    • 在大多数情况下,数据输入和清理工作占了 90%。
    猜你喜欢
    • 2018-05-29
    • 2012-05-11
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-15
    相关资源
    最近更新 更多