1
votes

I'm trying to plot the a data in pivot_long form to present as a heatmap using geom_tile. However I'm having trouble for ordering the tiles in the figure.

sample data https://drive.google.com/file/d/1WIjbN9-xP-1Wgc2Nx3GlterV8XhtnGyu/view?usp=sharing

Here is the figure I generated:

The problem is I want the y axis labels, aka "Drug.dose" ranked by numeric values high to low in the "none" part of the Combination added (factors set to have levels none, I30, I300.... I300_V100)

My code for plotting as below: By using reorder() on my y axis(How to preserve the order of tiles in geom_tile ggplot), it ranked from high to low by everything in the Combined added, thus you see my highest one in the none is TN 0.1 but it goes to the bottom of the figure because of all the zeros in I30, I300 etc. And there are other inconsistencies in the list.

How I can reorder just by the none section of the Combination added?

library(ggplot2)

m <- ggplot(data)+
  geom_tile(aes(x=Combination, y=reorder(Drug.dose,Avg.percent), fill=Avg.percent))+
  geom_text(aes(x=Combination, y=reorder(Drug.dose,Avg.percent), label=Avg.percent), size=3)+
  scale_fill_gradientn(colors=pal)+
  theme(legend.text = element_text(size=10, face="bold", color = "black"))+
  theme(axis.text.x = element_text(size = 15,  face="bold", color = "black")) +
  theme(axis.text.y = element_text(size = 9,  face="bold", color = "black")) +
  theme(axis.title.x = element_text(size = 15,  face="bold", color = "black", vjust = 3))+
  theme(axis.title.y = element_text(size = 15,  face="bold", color = "black", hjust = 0.5))+
  theme(plot.title = element_text(size = 16))+
  theme(strip.text.y  = element_text(size = 10, face = "bold", color = "black"))+
  scale_x_discrete(position ="top") +
  xlab("Combination added")+
  ylab("Treatments in the screen")+
  ggtitle("Cluster 1 Enriched in TN response")


print(m)

 

enter image description here

2

2 Answers

2
votes

Something like this? Just create a static variable that manages the colour gradient for ya.

library(tidyverse)
levels <- c("none","I30","I300","I30_V10","I300_V100","V10","V100" )

# Data directory %>%
  read_csv %>% 
  pivot_wider(names_from = Combination,
              values_from = Avg.percent) %>% 
  mutate(color = none) %>% 
  pivot_longer(cols = c("none", starts_with(c(c("I","V"), ignore.case = F))),
               names_to = "Combination",
               values_to = "Avg.percent") %>% 
  mutate(Combination = factor(Combination,
                              levels = levels))-> data

m <- ggplot(data)+
  geom_tile(aes(x=Combination, y=reorder(Drug.dose, color), fill=Avg.percent)) +
  geom_text(aes(x=Combination, y=reorder(Drug.dose, color), label=Avg.percent), size=3)+
  # scale_fill_gradientn(colors=pal)+
  ggsci::scale_fill_material("red") +
  theme(legend.text = element_text(size=10, face="bold", color = "black"))+
  theme(axis.text.x = element_text(size = 15,  face="bold", color = "black")) +
  theme(axis.text.y = element_text(size = 9,  face="bold", color = "black")) +
  theme(axis.title.x = element_text(size = 15,  face="bold", color = "black", vjust = 3))+
  theme(axis.title.y = element_text(size = 15,  face="bold", color = "black", hjust = 0.5))+
  theme(plot.title = element_text(size = 16))+
  theme(strip.text.y  = element_text(size = 10, face = "bold", color = "black"))+
  scale_x_discrete(position ="top") +
  xlab("Combination added")+
  ylab("Treatments in the screen")+
  ggtitle("Cluster 1 Enriched in TN response")

print(m)
1
votes

I think that the best way to do it is order your data before placing it in ggplot. There's probably a solution using tidyr or something else but i don't know much about it.

Get the paired values when Combination=="none", and order it by Avg.percent:

index = data[data$Combination=="none", c("Drug.dose", "Avg.percent")]
index = index[order(index$Avg.percent),]

Create a variable order that gives the value on index for each level in Drug.dose:

for(i in unique(data$Drug.dose)){
  data$order[data$Drug.dose==i] = index[index$Drug.dose==i,2]}

Then use order on the place of Avg.percent in reorder(). Output (on you order of levels "none" should be the first row):

enter image description here