1

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

ML33M
  • 341
  • 2
  • 19

2 Answers2

2

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)
Yang Liu
  • 36
  • 4
  • 1
    Hey, I first need to say very slick codes, and secondly, you literally just blew my mind with the ggsci::scale_fill_material("red") Palettes. When I clicked in to see all the journals, I was like great, gold. When I scroll down to see rick and morty, OMG! You see the original color on my figure was from Wes Anderson ... just wow, I love this color palettes. – ML33M Nov 05 '20 at 04:22
  • Okay sorry I was too excited. Now the code part, sorry I'm a retard biologist. would you mind help me understand the code? specifically why we need to pivot_wide first before pivot long again? and what the mutate() are doing? specifically the mutate(color = none). I guess this is the key to allow reorder by color later. You probably guess I don't even know what is "static variable that manages the colour gradient". I like the colours, and if I learn how to manipulate this then I can update all my figures to be consistent. – ML33M Nov 05 '20 at 04:25
  • ahhhhh now I see what happened once I break your %>% apart and realised the color=none is the none column, my bad, stupid naming. This is very simple and nice. – ML33M Nov 05 '20 at 05:19
1

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

  • 1
    I get the idea, this is something what I imaged too, the core idea is to append the same index to all rows in the final heatmap so when we order by the none subcategory we can achieve the goal right? very smart. but the for loop returns an error about the appending order column order. First R complains about the order column initialising, fine. second I think the value we retrieve from index and append to the order is wrong. – ML33M Nov 05 '20 at 04:00
  • index = index[order(index$Avg.percent),2] will make index a vector of avg.percent. So I have to make it index = index[order(index$Avg.percent), ] to keep the drug.dose and avg percent column. Then next in the for loop, data$order[data$Drug.dose==i] = index[index$Drug.dose==i,2] this will append the entire index$avg,percent into each row. – ML33M Nov 05 '20 at 04:02
  • 1
    You're right. The `,2` in the index shouldn't be there, i added after testing without it in R because i thought it'd be cleaner, but it doesn't work. – Ricardo Semião e Castro Nov 05 '20 at 12:14
  • 1
    all good man, still thank you for your contributions. I gave the tick to Liu since her code is easier to incorporate. But surely an upvote for your solution – ML33M Nov 06 '20 at 04:56