<p><strong>The element that is clustering your plot the most is the ggrepel labels</strong>, so that's what you need to work on. </p>

<p>To get to a readable number of labels, <strong>I would not remove random genes</strong>: you risk losing important info, be it genes that could be of interest to you or some of the most regulated. Incidentally that seems to happen on your example: you try plotting in red the label for Casp14, but it does not show on the plot, probably because the gene was removed in your sampling.</p>

<p>What you can do however is, as dc37 suggests, <strong>increase the thresholds for the labels</strong> (you can probably play around with the thresholds to see when it does become readable). This should also help with the plotting: you mention that generating the plot was taking a long time, but with the number of genes you are looking at (~10k-30k?), the geom_points() should not be a real problem (maybe a few seconds), however the ggrepel is the most computationnally expensive so that's what you should try to reduce.</p>

<p>This should get you started:</p>

<pre><code>ggplot(final_tumor, aes(x = Log2.fold.change,y = -log10(Adjusted.p.value), label = Feature.Name))+ 
  geom_point()+ 
  geom_text_repel(data = subset(final_tumor, Adjusted.p.value &lt; 0.001 &amp; abs(Log2.fold.change) &gt; 1 ), aes(label = Feature.Name))+ 
  geom_text_repel(data = subset(final_tumor, Feature.Name == "Casp14"), aes(label = Feature.Name), color = "red")
</code></pre>

<p>Notice everything plots the "final_tumor" object and not the "rep_final". Feel free to be even more stringent with the cutoffs if it's still taking too long to plot.</p>

<p>A bit outside of the score of your question, but I also wanted to mention that you should never be trying to label too many genes on a volcano plot: this type of graph is useful to visualize your data's p-value/FC distribution and highlight a subset of genes in this context (most regulated, genes regulated in another experiment, pathway of interest...), but if you label too many of them it will never be readable.</p>

<p>If you really want to be able to indentify all the genes on your graph, I would try an interactive visualization (like with <a href="https://plot.ly/r/" rel="nofollow noreferrer">plotly</a>). I'm not going to detail the code here but you could look in that direction! (However, as with ggrepel, you might need to remove some genes so that it does not "take forever").</p>

<p>Have fun :)</p>

CC BY-SA 4.0
2020-01-27T21:26:40.233Z
It's still taking quite a bit of time to plot.
mmpp
CC BY-SA 4.0
2020-01-29T05:52:44.843Z
@mmpp how long?
Kerkyra
CC BY-SA 4.0
2020-01-29T13:40:23.340Z
It's still going.
mmpp
CC BY-SA 4.0
2020-02-02T02:03:28.730Z
Any other suggestions?
mmpp
CC BY-SA 4.0
2020-01-27T13:59:56.470Z
2020-01-27T13:59:56.470Z
Kerkyra
<p>Aside from the <code>ggrepel</code> labels, another reason your volcano plot looks cluttered is the presence of the 4 very highly significant genes on the top right, which lead to the rest of the genes being squeezed into the x axis. For visualization purposes, you could try applying an inverse hyperbolic sine transformation (<code>asinh()</code> in R) to both your x/y axes, which should alleviate this squeezing while not distorting too much the overall volcano shape. Just be sure to also apply this transformation to any cutoff lines you are including in the plot.</p>

CC BY-SA 4.0
2024-02-27T03:34:25.933Z
2024-02-27T03:35:04.520Z
2024-02-27T03:35:04.520Z
razorofockham
<p>As we discussed in comments in your previous post: <a href="https://bioinformatics.stackexchange.com/questions/11231/pulling-out-a-certain-gene-in-a-volcano-plot/11232#11232">Pulling out a certain gene in a volcano plot</a>, in order to have less labeled genes on your volcano plot, you can specify more stringent cutoff.</p>
<p>For example, you can decide to display only genes with an absolute fold change superior to 2 by selecting the appropriate subset of your data:</p>
<pre class="lang-r prettyprint-override"><code>ggplot(rep_final, aes(x = Log2.fold.change,y = -log10(Adjusted.p.value), label = Feature.Name))+ 
  geom_point()+ 
  geom_text_repel(data = subset(rep_final, abs(Log2.fold.change) &gt; 2), aes(label = Feature.Name))+ 
  geom_text_repel(data = subset(final_tumor, Feature.Name == &quot;Casp14&quot;), aes(label = Feature.Name), 
                  color = &quot;red&quot;, size = 5)
</code></pre>
<p>Alternatively, you can maybe decide that a p value inferior to 0.05 is not enough stringent and decide to labeled only genes with an adjusted p value inferior to 0.00001 by doing:</p>
<pre class="lang-r prettyprint-override"><code>ggplot(rep_final, aes(x = Log2.fold.change,y = -log10(Adjusted.p.value), label = Feature.Name))+ 
  geom_point()+ 
  geom_text_repel(data = subset(rep_final, Adjusted.p.value &lt; 0.00001), aes(label = Feature.Name))+ 
  geom_text_repel(data = subset(final_tumor, Feature.Name == &quot;Casp14&quot;), aes(label = Feature.Name), 
                  color = &quot;red&quot;, size = 5)
</code></pre>
<p>Or, you can want to do a combination of both criteria by doing:</p>
<pre class="lang-r prettyprint-override"><code>ggplot(rep_final, aes(x = Log2.fold.change,y = -log10(Adjusted.p.value), label = Feature.Name))+ 
  geom_point()+ 
  geom_text_repel(data = subset(rep_final, abs(Log2.fold.change) &gt; 2 &amp; Adjusted.p.value &lt; 0.00001), aes(label = Feature.Name))+ 
  geom_text_repel(data = subset(final_tumor, Feature.Name == &quot;Casp14&quot;), aes(label = Feature.Name), 
                  color = &quot;red&quot;, size = 5)
</code></pre>
<p>At the end, I think it depends of what you are trying to demonstrate by presenting this volcano plot. Do you want to highlight some particular genes? Or do you want to display genes that are the most differentially expressed? If so, how many?</p>
<p>All of this depends of the scientific question underlying your experiments and why you came to make this volcano plot.</p>
<p>Hope this couple of example helps you to figure it out how to customize your volcano plot.</p>

CC BY-SA 4.0
2020-01-27T04:33:43.677Z
2024-02-27T16:29:26.343Z
2024-02-27T16:29:26.343Z
dc37
<p>I have generated a volcano plot with a differential expression file.</p>

<p>Code for inputing file:</p>

<pre class="lang-r prettyprint-override"><code>library(tidyr)
final_tumor &lt;- df %&gt;% pivot_longer(., -c(Feature.ID, Feature.Name), names_to = c("set",".value"), names_pattern = "(.+)_(.+)")

# A tibble: 80 x 6
Feature.ID Feature.Name set       Mean.Counts Log2.fold.change Adjusted.p.value
&lt;fct&gt;      &lt;fct&gt;        &lt;chr&gt;           &lt;dbl&gt;            &lt;dbl&gt;            &lt;dbl&gt;
  1 a          A            Cluster.1    0.000961            0.292           1     
2 a          A            Cluster.2    0.000902            0.793           1     
3 a          A            Cluster.3    0.00181             1.46            0.758 
4 a          A            Cluster.4    0.000642            0.269           1     
5 b          B            Cluster.1    0.000320            1.95            0.910 
6 b          B            Cluster.2    0.00180             4.77            0.154 
7 b          B            Cluster.3    0                   2.19            1     
8 b          B            Cluster.4    0                   1.66            1     
9 c          C            Cluster.1    0.00128            -2.01            0.0467
10 c          C            Cluster.2    0.00632             0.352           1     
# … with 70 more rows
</code></pre>

<p>Here the output of head(final_tumor)</p>

<pre class="lang-r prettyprint-override"><code># A tibble: 6 x 6
Feature.ID        Feature.Name set       Mean.Counts Log2.fold.change Adjusted.p.value
&lt;fct&gt;             &lt;fct&gt;        &lt;chr&gt;           &lt;dbl&gt;            &lt;dbl&gt;            &lt;dbl&gt;
  1 ENSG00000227232.5 WASH7P       Cluster.1     0                   1.50            1    
2 ENSG00000227232.5 WASH7P       Cluster.2     0                   1.73            1    
3 ENSG00000227232.5 WASH7P       Cluster.3     0                   1.77            1    
4 ENSG00000227232.5 WASH7P       Cluster.4     0.00114             4.30            0.293
5 ENSG00000227232.5 WASH7P       Cluster.5     0                   2.15            1    
6 ENSG00000227232.5 WASH7P       Cluster.6     0                   1.22            1 
</code></pre>

<p>And here is the output of tail(final_tumor):</p>

<pre class="lang-r prettyprint-override"><code># A tibble: 6 x 6
Feature.ID        Feature.Name set        Mean.Counts Log2.fold.change Adjusted.p.value
&lt;fct&gt;             &lt;fct&gt;        &lt;chr&gt;            &lt;dbl&gt;            &lt;dbl&gt;            &lt;dbl&gt;
  1 ENSG00000210196.2 MT-TP        Cluster.6       0.0699          -0.202           0.790  
2 ENSG00000210196.2 MT-TP        Cluster.7       0.0801           0.0386          1      
3 ENSG00000210196.2 MT-TP        Cluster.8       0.0711           0.0875          1      
4 ENSG00000210196.2 MT-TP        Cluster.9       0.0152          -2.31            0.00127
5 ENSG00000210196.2 MT-TP        Cluster.10      0.0147          -2.30            0.00612
6 ENSG00000210196.2 MT-TP        Cluster.11      0.122            0.762           1
</code></pre>

<p>Here is the code for generating volcano plot:</p>

<pre class="lang-r prettyprint-override"><code>library(ggplot2)
library(ggrepel)
ggplot(final_tumor, aes(x = Log2.fold.change,y = -log10(Adjusted.p.value), label = Feature.Name))+ 
  geom_point()+
  geom_text_repel(data = subset(final_tumor, Adjusted.p.value &lt; 0.05), 
                  aes(label = Feature.Name))+
  geom_text_repel(data = subset(final_tumor, Feature.Name == "Casp14"), 
                  aes(label = Feature.Name), color = "red")
</code></pre>

<p>Generating the ggplot with all the data was taking forever, it was suggested to select random rows of the dataframe: </p>

<pre><code>rep_final = final_tumor[sample(1:nrow(final_tumor), size = 1000), ]
</code></pre>

<p><a href="https://i.sstatic.net/nt36a.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/nt36a.png" alt="plot"></a></p>

<p>Then I did:</p>

<pre class="lang-r prettyprint-override"><code>ggplot(rep_final, aes(x = Log2.fold.change,y = -log10(Adjusted.p.value), label = Feature.Name))+ 
  geom_point()+ 
  geom_text_repel(data = subset(rep_final, Adjusted.p.value &lt; 0.05), aes(label = Feature.Name))+ 
  geom_text_repel(data = subset(final_tumor, Feature.Name == "Casp14"), aes(label = Feature.Name), color = "red")
</code></pre>

<p>Everything is very tight and cluttered. I want to show the top differentially expressed genes. How do I go about simplifying the plot? </p>

<p>Is there a way to do this on EnhancedVolcano, pulling out a certain gene?</p>

<pre><code>EnhancedVolcano(final_tumor, lab = as.character(final_tumor$FeatureName), x = 'Log2.fold.change', y = 'Adjusted.p.value', xlim = c(-8,8), title = 'Tumor', pCutoff = 10e-5, FCcutoff = 1.5, pointSize = 3.0, labSize = 3.0) 
</code></pre>

<r><bioconductor><ggplot2>
Making a volcano plot look less cluttered
# Making a volcano plot look less cluttered

(Asked by: username_0 on 2020-01-26)

I have generated a volcano plot with a differential expression file.
Code for inputing file:
library(tidyr)
final_tumor <- df %>% pivot_longer(., -c(Feature.ID, Feature.Name), names_to = c("set",".value"), names_pattern = "(.+)_(.+)")

# A tibble: 80 x 6
Feature.ID Feature.Name set       Mean.Counts Log2.fold.change Adjusted.p.value
                                                 
  1 a          A            Cluster.1    0.000961            0.292           1     
2 a          A            Cluster.2    0.000902            0.793           1     
3 a          A            Cluster.3    0.00181             1.46            0.758 
4 a          A            Cluster.4    0.000642            0.269           1     
5 b          B            Cluster.1    0.000320            1.95            0.910 
6 b          B            Cluster.2    0.00180             4.77            0.154 
7 b          B            Cluster.3    0                   2.19            1     
8 b          B            Cluster.4    0                   1.66            1     
9 c          C            Cluster.1    0.00128            -2.01            0.0467
10 c          C            Cluster.2    0.00632             0.352           1     
# … with 70 more rows

Here the output of head(final_tumor)
# A tibble: 6 x 6
Feature.ID        Feature.Name set       Mean.Counts Log2.fold.change Adjusted.p.value
                                                        
  1 ENSG00000227232.5 WASH7P       Cluster.1     0                   1.50            1    
2 ENSG00000227232.5 WASH7P       Cluster.2     0                   1.73            1    
3 ENSG00000227232.5 WASH7P       Cluster.3     0                   1.77            1    
4 ENSG00000227232.5 WASH7P       Cluster.4     0.00114             4.30            0.293
5 ENSG00000227232.5 WASH7P       Cluster.5     0                   2.15            1    
6 ENSG00000227232.5 WASH7P       Cluster.6     0                   1.22            1 

And here is the output of tail(final_tumor):
# A tibble: 6 x 6
Feature.ID        Feature.Name set        Mean.Counts Log2.fold.change Adjusted.p.value
                                                         
  1 ENSG00000210196.2 MT-TP        Cluster.6       0.0699          -0.202           0.790  
2 ENSG00000210196.2 MT-TP        Cluster.7       0.0801           0.0386          1      
3 ENSG00000210196.2 MT-TP        Cluster.8       0.0711           0.0875          1      
4 ENSG00000210196.2 MT-TP        Cluster.9       0.0152          -2.31            0.00127
5 ENSG00000210196.2 MT-TP        Cluster.10      0.0147          -2.30            0.00612
6 ENSG00000210196.2 MT-TP        Cluster.11      0.122            0.762           1

Here is the code for generating volcano plot:
library(ggplot2)
library(ggrepel)
ggplot(final_tumor, aes(x = Log2.fold.change,y = -log10(Adjusted.p.value), label = Feature.Name))+ 
  geom_point()+
  geom_text_repel(data = subset(final_tumor, Adjusted.p.value < 0.05), 
                  aes(label = Feature.Name))+
  geom_text_repel(data = subset(final_tumor, Feature.Name == "Casp14"), 
                  aes(label = Feature.Name), color = "red")

Generating the ggplot with all the data was taking forever, it was suggested to select random rows of the dataframe: 
rep_final = final_tumor[sample(1:nrow(final_tumor), size = 1000), ]


Then I did:
ggplot(rep_final, aes(x = Log2.fold.change,y = -log10(Adjusted.p.value), label = Feature.Name))+ 
  geom_point()+ 
  geom_text_repel(data = subset(rep_final, Adjusted.p.value < 0.05), aes(label = Feature.Name))+ 
  geom_text_repel(data = subset(final_tumor, Feature.Name == "Casp14"), aes(label = Feature.Name), color = "red")

Everything is very tight and cluttered. I want to show the top differentially expressed genes. How do I go about simplifying the plot? 
Is there a way to do this on EnhancedVolcano, pulling out a certain gene?
EnhancedVolcano(final_tumor, lab = as.character(final_tumor$FeatureName), x = 'Log2.fold.change', y = 'Adjusted.p.value', xlim = c(-8,8), title = 'Tumor', pCutoff = 10e-5, FCcutoff = 1.5, pointSize = 3.0, labSize = 3.0)

**Tags:** r, bioconductor, ggplot2

---

## 3 answers

### Answer by username_1 on 2020-01-27. Score: 2

The element that is clustering your plot the most is the ggrepel labels, so that's what you need to work on. 
To get to a readable number of labels, I would not remove random genes: you risk losing important info, be it genes that could be of interest to you or some of the most regulated. Incidentally that seems to happen on your example: you try plotting in red the label for Casp14, but it does not show on the plot, probably because the gene was removed in your sampling.
What you can do however is, as dc37 suggests, increase the thresholds for the labels (you can probably play around with the thresholds to see when it does become readable). This should also help with the plotting: you mention that generating the plot was taking a long time, but with the number of genes you are looking at (~10k-30k?), the geom_points() should not be a real problem (maybe a few seconds), however the ggrepel is the most computationnally expensive so that's what you should try to reduce.
This should get you started:
ggplot(final_tumor, aes(x = Log2.fold.change,y = -log10(Adjusted.p.value), label = Feature.Name))+ 
  geom_point()+ 
  geom_text_repel(data = subset(final_tumor, Adjusted.p.value < 0.001 & abs(Log2.fold.change) > 1 ), aes(label = Feature.Name))+ 
  geom_text_repel(data = subset(final_tumor, Feature.Name == "Casp14"), aes(label = Feature.Name), color = "red")

Notice everything plots the "final_tumor" object and not the "rep_final". Feel free to be even more stringent with the cutoffs if it's still taking too long to plot.
A bit outside of the score of your question, but I also wanted to mention that you should never be trying to label too many genes on a volcano plot: this type of graph is useful to visualize your data's p-value/FC distribution and highlight a subset of genes in this context (most regulated, genes regulated in another experiment, pathway of interest...), but if you label too many of them it will never be readable.
If you really want to be able to indentify all the genes on your graph, I would try an interactive visualization (like with plotly). I'm not going to detail the code here but you could look in that direction! (However, as with ggrepel, you might need to remove some genes so that it does not "take forever").
Have fun :)

> **Comments:**
> **username_0**: It's still taking quite a bit of time to plot.  
> **username_1**: @mmpp how long?  
> **username_0**: It's still going.  
> **username_0**: Any other suggestions?  

---

### Answer by username_2 on 2024-02-27. Score: 2

Aside from the `ggrepel` labels, another reason your volcano plot looks cluttered is the presence of the 4 very highly significant genes on the top right, which lead to the rest of the genes being squeezed into the x axis. For visualization purposes, you could try applying an inverse hyperbolic sine transformation (`asinh()` in R) to both your x/y axes, which should alleviate this squeezing while not distorting too much the overall volcano shape. Just be sure to also apply this transformation to any cutoff lines you are including in the plot.


---

### Answer by username_3 on 2020-01-27. Score: 1

As we discussed in comments in your previous post: Pulling out a certain gene in a volcano plot, in order to have less labeled genes on your volcano plot, you can specify more stringent cutoff.
For example, you can decide to display only genes with an absolute fold change superior to 2 by selecting the appropriate subset of your data:
ggplot(rep_final, aes(x = Log2.fold.change,y = -log10(Adjusted.p.value), label = Feature.Name))+ 
  geom_point()+ 
  geom_text_repel(data = subset(rep_final, abs(Log2.fold.change) > 2), aes(label = Feature.Name))+ 
  geom_text_repel(data = subset(final_tumor, Feature.Name == "Casp14"), aes(label = Feature.Name), 
                  color = "red", size = 5)

Alternatively, you can maybe decide that a p value inferior to 0.05 is not enough stringent and decide to labeled only genes with an adjusted p value inferior to 0.00001 by doing:
ggplot(rep_final, aes(x = Log2.fold.change,y = -log10(Adjusted.p.value), label = Feature.Name))+ 
  geom_point()+ 
  geom_text_repel(data = subset(rep_final, Adjusted.p.value < 0.00001), aes(label = Feature.Name))+ 
  geom_text_repel(data = subset(final_tumor, Feature.Name == "Casp14"), aes(label = Feature.Name), 
                  color = "red", size = 5)

Or, you can want to do a combination of both criteria by doing:
ggplot(rep_final, aes(x = Log2.fold.change,y = -log10(Adjusted.p.value), label = Feature.Name))+ 
  geom_point()+ 
  geom_text_repel(data = subset(rep_final, abs(Log2.fold.change) > 2 & Adjusted.p.value < 0.00001), aes(label = Feature.Name))+ 
  geom_text_repel(data = subset(final_tumor, Feature.Name == "Casp14"), aes(label = Feature.Name), 
                  color = "red", size = 5)

At the end, I think it depends of what you are trying to demonstrate by presenting this volcano plot. Do you want to highlight some particular genes? Or do you want to display genes that are the most differentially expressed? If so, how many?
All of this depends of the scientific question underlying your experiments and why you came to make this volcano plot.
Hope this couple of example helps you to figure it out how to customize your volcano plot.


---

