如何使用特定因子顺序对ggplot对象重新排序

时间:2019-02-20 19:48:17

标签: r ggplot2

我正在尝试在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命令还是在创建传递到绘图函数的数据框对象之前对矩阵中的某些东西进行重新排序,我都会对固定图纸顺序的策略有任何见解。 / p>

谢谢

2 个答案:

答案 0 :(得分: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创建

答案 1 :(得分:0)

类似于Calum您的回答,只是我先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