在 geom_tile 中按面拆分重叠图块

Split overlapping tiles by facet in geom_tile

我堆叠了一个数据框,显示 values 每 idgroups:

df <- tibble::tibble(id = c(LETTERS[1:6], LETTERS[1:5]),
                     value = c(paste0("V", 1:6), paste0("V", 1:5)),
                     group = c(rep("group_1", 6), rep("group_2", 5)))

df
#> # A tibble: 11 x 3
#>    id    value group  
#>    <chr> <chr> <chr>  
#>  1 A     V1    group_1
#>  2 B     V2    group_1
#>  3 C     V3    group_1
#>  4 D     V4    group_1
#>  5 E     V5    group_1
#>  6 F     V6    group_1
#>  7 A     V1    group_2
#>  8 B     V2    group_2
#>  9 C     V3    group_2
#> 10 D     V4    group_2
#> 11 E     V5    group_2

我想创建一个热图,显示每个 value (x) 对于每个 id (y) 在 group 秒(填充)中的“可用性”:

ggplot(df, aes(x = id, y = value, fill = group)) + 
  geom_tile()

问题是 fill 重叠:我只能看到 F/V6 仅在 group_1 中(而不在 group_2 中)。但是,对于 ID A 到 E,值 V1 到 V5 在 两个 组中都可用,因此 group_2 的颜色在 group_1 之上,因此看起来它们仅在 group_2.

中可用

如果我使用facet_wrap(),可用性更明显:

ggplot(df, aes(x = id, y = value, fill = group)) + 
  geom_tile() + 
  facet_wrap("group")

然而,在我的真实设置中,热图非常大,因此很难比较哪些值在哪个组中可用。

如果值在两个组中都可用,是否可以将每个图块分成两半,如果只在一个组中存在,是否可以保持完整?所以在上面的第一个图中,蓝色方块将被分成两半(同时显示蓝色和红色),而红色方块将保持原样。


更新

感谢 stefan 关于使用 position = "dodge" 的出色提示。但是,我注意到我的问题实际上比我上面的 reprex 复杂一点:每个 value 可能出现在每个 group 的多个 id 中。当使用 position = "dodge" 时,ggplot2 然后将每个 id“列”“划分”为与每个 value 在此 id:

中出现的部分一样多的部分

df <- tibble::tibble(id = c("A", "A",  "A", "B", "B", "C", "C", "C", "A", "A", "B", "B", "C", "C"),
                     value = c("V1", "V2", "V3", "V1", "V3", "V1", "V2", "V4", "V1", "V2", "V1", "V3", "V1", "V4"),
                     group = c(rep("group_1", 8), rep("group_2", 6)))

df
#> # A tibble: 14 x 3
#>    id    value group  
#>    <chr> <chr> <chr>  
#>  1 A     V1    group_1
#>  2 A     V2    group_1
#>  3 A     V3    group_1
#>  4 B     V1    group_1
#>  5 B     V3    group_1
#>  6 C     V1    group_1
#>  7 C     V2    group_1
#>  8 C     V4    group_1
#>  9 A     V1    group_2
#> 10 A     V2    group_2
#> 11 B     V1    group_2
#> 12 B     V3    group_2
#> 13 C     V1    group_2
#> 14 C     V4    group_2

ggplot(df, aes(x = id, y = value, fill = group)) + 
  geom_tile(position = "dodge")

您可以看到,在“A 列”中,三个图块并排放置,将可用的 space 一分为三。我想要实现的是将“A 列”中的这三对图块绘制在彼此之上,以便它们对齐,使用分配给每个值的“A 列”的整个可用 space。

一种选择是使用 position="dodge":

library(ggplot2)

ggplot(df, aes(x = id, y = value, fill = group)) + 
  geom_tile(position = "dodge")


更新

您可以尝试在 group aes 上映射组:

ggplot(df, aes(x = id, y = value, fill = group, group = group)) + 
  geom_tile(position = "dodge", color = "black") # adding 'color' for borders

如果你想要三角形,认为你可能需要使用一些争论和 geom_polygon 手动完成,例如:

library(ggplot2)

df <- tibble::tibble(x = c(LETTERS[1:6], LETTERS[1:5]),
                     y = c(paste0("V", 1:6), paste0("V", 1:5)),
                     group = c(rep("group_1", 6), rep("group_2", 5)))

df1    <- df[!duplicated(interaction(df$x, df$y)),]
df2    <- df[duplicated(interaction(df$x, df$y)),]
df2    <- df[rep(seq(nrow(df)), each = 3),]
df2$x1 <- as.numeric(as.factor(df2$x))
df2$y1 <- as.numeric(as.factor(df2$y))
df2$x1 <- df2$x1 + c(-0.5, 0.5, 0.5)
df2$y1 <- df2$y1 + c(-0.5, -0.5, 0.5)
df2$z  <- rep(seq(nrow(df2)/3), each = 3)

ggplot(df1, aes(x = x, y = y, fill = group)) + 
  geom_tile() +
  geom_polygon(data = df2, aes(x = x1, y = y1, group = z))

reprex package (v2.0.1)

创建于 2022-02-16