Hil*_*ary 4 visualization r heatmap ggplot2
我有分类数据,我想映射使用热图(geom_tile)的频率,就像下面的示例一样:
data("mtcars")
freq <- data.frame(xtabs(~cyl + gear, mtcars)) #count number of 4,6,8 cyl cars by gear
ggplot(freq, aes(cyl, gear)) +
  geom_tile(aes(fill = Freq)) + 
  scale_fill_gradient(low = "white",high = "steelblue")

但我想根据显着或不显着结果(0-1 值)的比例分割每个图块。在此示例中,我将生成相同的频率计数,但区分自动传输和手动传输 ( am)
freq_am <- data.frame(xtabs(~cyl + gear + am, mtcars))
print(freq_am)
   #cyl gear am Freq
      4    3  0    1
      6    3  0    2
      8    3  0   12
      4    4  0    2
      6    4  0    2
      8    4  0    0
      4    5  0    0
      6    5  0    0
      8    5  0    0
      4    3  1    0
      6    3  1    0
      8    3  1    0
      4    4  1    6
      6    4  1    2
      8    4  1    0
      4    5  1    2
      6    5  1    1
      8    5  1    2
生成的热图将(例如)蓝色表示 的值,红色am==0表示的值。每个图块将根据该类型自动()或手动()汽车的比例进行划分(沿对角线?)。蓝色和红色的色调将与计数成比例,就像渐变已经反映一样。am==1am==0am==1
例如:
左上方的图块 (4,5) 将完全呈浅红色,因为所有 4 缸、5 档汽车(数量 = 2)都是手动的
中间左侧的图块 (4,4) 将是 1/4 蓝色和 3/4 红色,因为 25% 的 4 档 4 缸汽车是自动的(计数 = 2),75% 是手动的(计数 = 6)
左下方的图块 (4,3) 将完全是最浅的蓝色,因为所有 4 缸、3 档汽车(计数 = 1)都是自动的
这是通过操纵频率计数使它们变为负数来回答该问题的第二次且希望是完整的尝试am==1。与第一次尝试的区别在于它geom_col(position = "fill")是用来代替geom_tile()绘图的。
注意:我没有编辑第一个答案,因为OP已经对其发表了评论,我最终可能会删除第一个不完整的答案。
freq_am <-data.frame(xtabs(~cyl + gear + am, mtcars))
freq_am$Freq_am <- freq_am$Freq * (-1)^as.integer(as.character(freq_am$am))
这将创建一个新列Freq_am,其中计数与if (手动)Freq相乘。使用逻辑值求幂是一个需要避免的技巧。-1am == 1ifelse
有两种可能性可以实现所需的热图式外观。
p <- ggplot(freq_am, (aes(x = cyl, y = Freq, fill = Freq_am))) + 
  geom_col(position = "fill", width = 1) + 
  scale_fill_gradient2() +
  facet_grid(gear ~ ., as.table = FALSE, switch = "y") + 
  scale_y_continuous(expand = c(0, 0)) + 
  scale_x_discrete(expand = c(0, 0))
p
Freq这将创建一个vs的堆叠条形图cyl,其中geom_col()条形垂直 ( position = "fill") 和水平 ( width = 1) 拉伸以填充绘图区域。此外,函数expand = c(0, 0)的参数scale指示ggplot不要像往常一样扩展轴。请注意,x 轴是离散的,因为xtabs()已强制cyl分解。
facet_grid()用于模拟 y 轴,其grid值按升序排列 ( as.table = FALSE)。switch = "y"将面板条移至左侧。
scale_fill_gradient2()默认情况下使用方便的发散配色方案,自动变速箱的汽车数量显示为蓝色,手动变速箱的汽车数量显示为红色。  
现在,我们需要删除热图不需要的所有装饰和空间。最后,y轴标签被重命名:
p + theme(panel.grid = element_blank()
          , axis.ticks = element_blank()
          , axis.text.y = element_blank()
          , strip.background = element_blank()
          , panel.spacing.y = unit(0, "pt")
) + 
  ylab("gear")
这种方法的缺点是图块之间缺乏边界。因此,如果相邻的图块具有与例如6缸、3齿轮和4齿轮分别的图块相同的颜色,则很难区分计数的份额。
此变体在图块之间添加了边框。边框的宽度可以灵活调整:
p <- ggplot(freq_am, (aes(x = 1, y = Freq, fill = Freq_am))) + 
  geom_col(position = "fill") + 
  scale_fill_gradient2() +
  facet_grid(gear ~ cyl, as.table = FALSE, switch = "both") +
  scale_y_continuous(expand = c(0, 0)) + 
  scale_x_continuous(expand = c(0, 0))
p
在这里,我们用于facet_grid()两个方向。对于每个面板,使用上述方法Freq绘制与虚拟变量的关系。由于虚拟变量是数字,我们不需要参数。现在两个轴都是连续的。1geom_col()1widthgeom_col()
同样,我们需要删除一些装饰并重命名 x 轴和 y 轴上的标签:
p + theme(panel.grid = element_blank()
        , axis.ticks = element_blank()
        , axis.text = element_blank()
        , strip.background = element_blank()
        # , panel.spacing = unit(0, "pt")
  ) + 
  xlab("cyl") + ylab("gear")
现在,我们确实有了一个带有图块之间边框的热图。为了删除边框或调整宽度,您可以取消注释该行panel.spacing并更改值。
| 归档时间: | 
 | 
| 查看次数: | 6425 次 | 
| 最近记录: |