如何按照特定因子顺序重新排序 ggplot 对象

3

我想在ggplot中制作成对热图。我试图避免使用其他相关性绘图程序,因为它们不支持ggplot中的某些下游美学更改。

我可以使用默认级别生成所需的绘图:

library(reshape2)
library(dplyr)

mat <- round(cor(mtcars[,2:length(mtcars)]),2)
mat[lower.tri(mat)] <- NA
df <- melt(mat) %>% drop_na()
ggplot(data=df, aes(x=Var1, y=Var2, fill=value)) + geom_tile()

enter image description here

然而,假设由于某种原因这些成对比较的顺序很重要,我真正需要绘制的是不同的顺序。我在其他图中使用的方法是使用factor(df$x, levels = c("some", "particular", "order),但如果我在这个实例中尝试类似的方法,则图块的顺序也会翻转。
mat <- round(cor(mtcars[,2:length(mtcars)]),2)
mat[lower.tri(mat)] <- NA
df <- melt(mat) %>% drop_na()
DesiredOrder <- c("cyl", "carb", "disp", "hp", "drat", "wt", "qsec", "vs", "am", "gear")
df$Var1 <- factor(df$Var1, levels = DesiredOrder)
df$Var2 <- factor(df$Var2, levels = DesiredOrder)
ggplot(data=df, aes(x=Var1, y=Var2, fill=value)) + geom_tile()

enter image description here

似乎这个问题与提供给 dcast 命令的矩阵顺序有关,但也许我可以在事后通过其他方式控制最终的绘图顺序。无论是在 ggplot 命令中还是在创建传递到绘图函数的数据框对象之前重新排列矩阵中的内容,我都希望能得到任何有关固定绘图顺序的策略的见解。谢谢。

1
顺序没问题,但“问题”在于你只选择了相关矩阵的下三角,而该矩阵本身是按特定顺序计算的。你需要重新排序矩阵行,然后再选择其下三角。 - joran
好的,谢谢@joran;为了使用我想要的顺序向量重新排序矩阵行,就像示例中的DesiredOrder对象一样,似乎mat[order(DesiredOrder),]并没有按照我预期的方式进行行重排。有什么想法吗? 再次感谢。 - Devon O'Rourke
1
这样做可以吗?mat <- mtcars[, DesiredOrder]; mat <- round(cor(mat), 2) - Rui Barradas
2个回答

0

与Calum You的答案类似,不同之处在于我会先进行矩阵的 gather 操作,然后使用 filter 来删除对应于下三角的行:

library(tidyverse)
mat <- round(cor(mtcars[,2:length(mtcars)]),2)
DesiredOrder <- c("cyl", "carb", "disp", "hp", "drat", "wt", "qsec", "vs", "am", "gear")

mat %>%
  as_tibble(rownames = "var1") %>%
  gather(var2, value, -var1) %>%
  mutate_at(vars(var1, var2), ~ factor(., levels = DesiredOrder)) %>%
  filter(as.integer(var1) <= as.integer(var2)) %>%
  ggplot() +
  geom_tile(aes(x = var1, y = var2, fill = value))

我相信结果的图应该是一样的,至少基于这个例子。

plot


0
如评论所建议,您需要重新排序矩阵,并取其下三角,以使在gathermelt)时保留正确的观测值。以下是您的代码的管道版本,其中主要添加是在删除下三角单元格之前进行重新排序。其他更改包括使用gather(na.rm = TRUE)mutate_at来节省几行代码。
library(tidyverse)
mat <- round(cor(mtcars[,2:length(mtcars)]),2)
DesiredOrder <- c("cyl", "carb", "disp", "hp", "drat", "wt", "qsec", "vs", "am", "gear")

mat %>%
  `[`(DesiredOrder, DesiredOrder) %>%
  `[<-`(lower.tri(.), NA) %>%
  as_tibble(rownames = "var1") %>%
  gather(var2, value, -var1, na.rm = TRUE) %>%
  mutate_at(vars(var1, var2), ~ factor(., levels = DesiredOrder)) %>%
  ggplot() +
  geom_tile(aes(x = var1, y = var2, fill = value))

reprex package (v0.2.1)于2019年02月20日创建


对我来说,像 %>% `[<-`() 这样的语法很难读懂。有没有更符合 tidyverse 风格的写法? - bdemarest
如果你想的话,你可以使用 magrittraliases extractinset。不过我会像这样引用它们:magrittr::extract。因为如果不这样,你必须明确地加载 magrittr,而且这会导致一些名称冲突。说实话,我只是习惯了使用反引号格式。 - Calum You

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接