# Density plots

The density plot was already presented in the previous subchapter. Density plots are used to depict the distribution of a numeric variable. Every density plot can be viewed as a derivative of a histogram. Therefore, its applications are similar to those of a histogram. Density plots can be an effective way of visualizing concentration distributions of lipids or metabolites in biological materials. Check out the selected example published in Nature:

* T. Takeuchi et al. Gut microbial carbohydrate metabolism contributes to insulin resistance. DOI: <https://doi.org/10.1038/s41586-023-06466-x> - Fig. 1d & 2b, f (*the authors of a manuscript published in Nature used density plots, e.g., for presenting and comparing fecal levels of monosaccharides across experimental groups (as decimal logarithm), or HOMA-IR, BMI, triglycerides (TG) and HDL-C levels among the participant clusters*).&#x20;

## Preparing density plots via DataExplorer (level: basic)

DataExplorer enables producing a simple density plot through plot\_density():

```r
# Calling library:
library(DataExplorer)

# Reading about plot_density:
?plot_density()

# Preparing plot - PLOT A
data %>%
  filter(Label == 'N') %>%
  select(`SM 41:1;O2`) %>%
  plot_density(theme_config = 
                 list(panel.background = element_blank(),
                      axis.line.x = element_line(color = 'black'),
                      axis.line.y = element_line(color = 'black')),
               geom_density_args = list(color = 'royalblue', linewidth = 1)
               ) 
               
# Preparing plot - PLOT B
data %>%
  filter(Label == 'T') %>%
  select(`SM 41:1;O2`) %>%
  plot_density(theme_config = 
                 list(panel.background = element_blank(),
                      axis.line.x = element_line(color = 'black'),
                      axis.line.y = element_line(color = 'black')),
               geom_density_args = list(color = 'red2', linewidth = 1)
               )
```

Basic plot customization was performed using **theme\_config** argument. We delivered a list with parameters to be changed, e.g., we removed the classic ggplot2 gray background using **panel.backgroud** and setting it **element\_blank()**:

```r
plot density(theme_config = list(panel.background = element_blank())
```

Then, we changed the x-y axes color to black through **axis.line.x** and **axis.line.y**:

```r
# Customizing the theme:
plot_density(theme_config = 
                 list(panel.background = element_blank(),
                      axis.line.x = element_line(color = 'black'),
                      axis.line.y = element_line(color = 'black'))
```

Finally, we changed the colors of the density plot curves to 'royalblue or 'red2', and linewidth to 1, using **geom\_density\_args** and a list containing information about a **color** and **linewidth**:

```r
# Changing color of density plot curves:
plot_density(geom_density_args = list(color = 'red2', linewidth = 1))
```

We obtain the following plots:

<figure><img src="/files/nLyucU5gukJ1ru4EDtdB" alt=""><figcaption><p>Density plots obtained through plot_density() from the DataExplorer.</p></figcaption></figure>

Such simple plots can be used for a quick data inspection.

## Preparing density plots via ggpubr (level: intermediate)

The ggpubr package contains function ggdensity(). We will show you how to prepare a density plot for a single lipid and multiple lipids:

```r
# Calling library
library(ggpubr)

# Reading the documentation about the function:
?ggdensity()

# PLOT A: Density plots for a single lipid (through wide tibble):
data %>%
  filter(Label != 'PAN') %>%
  select(`Label`,`SM 41:1;O2`) %>%
  ggdensity(x = "SM 41:1;O2",  # As x - you put name of the selected column
              color = "Label",
              fill = "Label",
              rug = T,
              palette = c('royalblue', 'red2'))
              
# PLOT B: Density plots for multiple lipids (through long tibble):
data %>%
  filter(Label != 'PAN') %>%
  select(`Label`,
         `SM 39:1;O2`,
         `SM 40:1;O2`,
         `SM 41:1;O2`,
         `SM 42:1;O2`) %>%
  pivot_longer(cols = `SM 39:1;O2`:`SM 42:1;O2`,
               names_to = 'Lipids',
               values_to = 'Concentrations') %>%
  ggdensity(x = "Concentrations",  # As x - you put column containing concentrations.
              color = "Label",
              fill = "Label",
              rug = T,
              palette = c('royalblue', 'red2')) +
  facet_grid(. ~ Lipids, scales = "free_x")
```

The plots:

<figure><img src="/files/4gFcAtoxgrQfe2PgTuVx" alt=""><figcaption><p>Density plots prepared using ggdensity() function from the ggpubr package.</p></figcaption></figure>

## Preparing density plots via ggplot2 (level: advanced)

As you know from the previous example with histograms, we can add a layer with a density plot using geom\_density(). Take a look at the examples below  - for a single lipid and multiple lipids. To customize the plot a bit more, we added mean values to them:

```r
# PLOT A: Plot for a single lipid:
# We need to compute means:
means <-
  data %>%
  filter(Label != 'PAN') %>%
  select(`Label`,
         `SM 41:1;O2`) %>%
  group_by(Label) %>%
  summarise(mean = mean(`SM 41:1;O2`))

# PLOT A:
data %>%
  filter(Label != 'PAN') %>%
  select(`Label`,
         `SM 41:1;O2`) %>%
  ggplot(aes(x = `SM 41:1;O2`, 
           color = `Label`,
           fill = `Label`)) + 
  geom_density(alpha = 0.5) +
  geom_vline(xintercept = means$mean, 
             colour = c('darkblue', 'red2'), 
             linetype = 'dashed',
             linewidth = 1) +
  scale_color_manual(values = c('royalblue', 'red2')) +
  scale_fill_manual(values = c('royalblue', 'red2')) +
  theme_bw() 
  
# PLOT B: Multiple lipids:
# Computing mean values for vlines:
means <- 
  data %>%
  filter(`Label` != "PAN") %>%
  droplevels() %>%
  select(`Label`,
         `SM 39:1;O2`,
         `SM 40:1;O2`,
         `SM 41:1;O2`,
         `SM 42:1;O2`) %>%
  pivot_longer(cols = `SM 39:1;O2`:`SM 42:1;O2`,
               names_to = "Lipids",
               values_to = "Concentrations") %>%
  group_by(Label, Lipids) %>%
  summarise(mean = mean(Concentrations))

# PLOT B:
data %>%
  filter(`Label` != "PAN") %>%
  droplevels() %>%
  select(`Label`,
         `SM 39:1;O2`,
         `SM 40:1;O2`,
         `SM 41:1;O2`,
         `SM 42:1;O2`) %>%
  pivot_longer(cols = `SM 39:1;O2`:`SM 42:1;O2`,
               names_to = "Lipids",
               values_to = "Concentrations") %>%
  ggplot(aes(x = `Concentrations`, 
           color = `Label`,
           fill = `Label`)) + 
  geom_density(alpha = 0.5) +
  geom_vline(data = means,
             aes(xintercept = mean),
             linetype = 'dashed',
             linewidth = 1,
             colour = rep(c('darkblue', 'red2'),
                          each = 4)) +
  scale_color_manual(values = c('royalblue', 'red2')) +
  scale_fill_manual(values = c('royalblue', 'red2')) +
  theme_bw() +
  facet_grid(. ~ Lipids, scales = "free_x")
```

The output:

<figure><img src="/files/p69Xtw68LntT0TEKWhh6" alt=""><figcaption><p>Density plots obtained using ggplot2 library.</p></figcaption></figure>

It is possible to plot one density graph up, while the other down. Such a chart is known as a mirror density chart. This plot was inspired by an excellent source of ideas for beautiful R charts - R graph gallery:

{% embed url="<https://r-graph-gallery.com/density_mirror_ggplot2.html>" %}
R graph gallery - mirror density plots
{% endembed %}

```r
# Preparing data and computing mean values:
data.N <- 
  data %>%
  filter(Label == 'N') %>%
  select(`Label`,
           `SM 41:1;O2`)


mean.N <- 
  data %>%
  filter(Label == 'N') %>%
  select(`Label`,
         `SM 41:1;O2`) %>%
  summarise(mean = mean(`SM 41:1;O2`))


data.T <- 
  data %>%
  filter(Label == 'T') %>%
  select(`Label`,
         `SM 41:1;O2`)

mean.T <- 
  data %>%
  filter(Label == 'T') %>%
  select(`Label`,
         `SM 41:1;O2`) %>%
  summarise(mean = mean(`SM 41:1;O2`))

# The final plot:
ggplot(data.N, aes(x = `SM 41:1;O2`)) + 
    geom_density(aes(y = ..density..), 
                 fill = 'royalblue', 
                 alpha = 0.4) + 
    geom_label(aes(x = 20, 
                   y = 0.10, 
                   label = "Healthy volunteers (N)"), 
               color = "royalblue") +
    geom_segment(data = mean.N,
             aes(x = mean,
                 xend = mean,
                 y = +Inf,
               yend = 0),
             linetype = 'dashed',
             linewidth = 1,
             colour = 'darkblue') +
    geom_density(data = data.T, 
                 aes(x = `SM 41:1;O2`, y = -..density..), 
                 fill = 'red2', 
                 alpha = 0.4) +
    geom_label(aes(x = 20, 
                   y = -0.10, 
                   label = "Patients with PDAC (T)"), 
               color = "red2") +
    geom_segment(data = mean.T,
               aes(x = mean,
                   xend = mean,
                   y = -Inf,
                   yend = 0),
               linetype = 'dashed',
               linewidth = 1,
               colour = 'red2')+
    theme_bw() 
```

The final plot:

<figure><img src="/files/3CQXO2ws7yehswM3Oij5" alt=""><figcaption><p>Mirror density plot inspired by R graph gallery.</p></figcaption></figure>

We can modify the code to obtain mirror density plots for multiple lipids at once:

```r
# Selecting data and computing means:
data.N <- 
  data %>%
  filter(Label == 'N') %>%
  select(`Label`,
         `SM 39:1;O2`,
         `SM 40:1;O2`,
         `SM 41:1;O2`,
         `SM 42:1;O2`) %>%
  pivot_longer(cols = `SM 39:1;O2`:`SM 42:1;O2`,
               names_to = 'Lipids',
               values_to = 'Concentrations')

mean.N <- 
  data %>%
  filter(Label == 'N') %>%
  select(`Label`,
         `SM 39:1;O2`,
         `SM 40:1;O2`,
         `SM 41:1;O2`,
         `SM 42:1;O2`) %>%
  pivot_longer(cols = `SM 39:1;O2`:`SM 42:1;O2`,
               names_to = 'Lipids',
               values_to = 'Concentrations') %>%
  group_by(Lipids, Label) %>%
  summarise(mean = mean(`Concentrations`))

data.T <- 
  data %>%
  filter(Label == 'T') %>%
  select(`Label`,
         `SM 39:1;O2`,
         `SM 40:1;O2`,
         `SM 41:1;O2`,
         `SM 42:1;O2`) %>%
  pivot_longer(cols = `SM 39:1;O2`:`SM 42:1;O2`,
               names_to = 'Lipids',
               values_to = 'Concentrations')

mean.T <- 
  data %>%
  filter(Label == 'T') %>%
  select(`Label`,
         `SM 39:1;O2`,
         `SM 40:1;O2`,
         `SM 41:1;O2`,
         `SM 42:1;O2`) %>%
  pivot_longer(cols = `SM 39:1;O2`:`SM 42:1;O2`,
               names_to = 'Lipids',
               values_to = 'Concentrations') %>%
  group_by(Lipids, Label) %>%
  summarise(mean = mean(`Concentrations`))
  
# Creating plot (without annotations):
ggplot(data.N, aes(x = `Concentrations`)) + 
  geom_density(aes(y = ..density..), 
               fill = 'royalblue', 
               alpha = 0.4) + 
  geom_segment(data = mean.N,
               aes(x = mean,
                   xend = mean,
                   y = +Inf,
                   yend = 0),
               linetype = 'dashed',
               linewidth = 1,
               colour = 'darkblue') +
  geom_density(data = data.T, 
               aes(x = `Concentrations`, y = -..density..), 
               fill = 'red2', 
               alpha = 0.4) +
  geom_segment(data = mean.T,
               aes(x = mean,
                   xend = mean,
                   y = -Inf,
                   yend = 0),
               linetype = 'dashed',
               linewidth = 1,
               colour = 'red2')+
  theme_bw() +
  facet_grid(. ~ Lipids, scales = 'free_x') 
```

We obtain the following plot:

<figure><img src="/files/DOWt2R5Khkk3WtHwid0q" alt=""><figcaption><p>Multiple mirror density plots for multiple SM species.</p></figcaption></figure>

We can also add annotations to each plot. Annotations must be delivered through geom\_text() as a data frame with labels and coordinates if multiple panels are created through facet\_grid(). Here, we will use exemplary annotations: "Control - N" and "Patient - T" :

```r
# Creating data frame with exemplary annotations:
annotations <- 
  data.frame(
    label = rep(c("Controls - N", "Patients - T"), each = 4),
    Lipids = c("SM 39:1;O2", "SM 40:1;O2", "SM 41:1;O2", "SM 42:1;O2"),
    x = c(9, 45, 20, 25, 9, 40, 20, 20),
    y = c(0.2, 0.2, 0.2, 0.2, -0.2, -0.2,-0.2,-0.2))
    
# Adding annotations via geom_text():
ggplot(data.N, aes(x = `Concentrations`)) + 
  geom_density(aes(y = ..density..), 
               fill = 'royalblue', 
               alpha = 0.4) + 
  geom_segment(data = mean.N,
               aes(x = mean,
                   xend = mean,
                   y = +Inf,
                   yend = 0),
               linetype = 'dashed',
               linewidth = 1,
               colour = 'darkblue') +
  geom_density(data = data.T, 
               aes(x = `Concentrations`, y = -..density..), 
               fill = 'red2', 
               alpha = 0.4) +
  geom_segment(data = mean.T,
               aes(x = mean,
                   xend = mean,
                   y = -Inf,
                   yend = 0),
               linetype = 'dashed',
               linewidth = 1,
               colour = 'red2')+
  theme_bw() +
  facet_grid(. ~ Lipids, scales = 'free_x') +
  geom_text(data = annotations,
            aes(x = x, 
                y = y, 
                label = label, 
                color = label), 
            show.legend = F) + 
  scale_color_manual(values = (c('royalblue', 'red2')))
```

We obtain finally:

<figure><img src="/files/18kc3IlsV8TVl68xXhHc" alt=""><figcaption><p>Multiple mirror density plots with annotations.</p></figcaption></figure>

As annotations, one could add, for example, some additional clinical data, the exact value of mean and median concentration, etc.&#x20;


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://laboratory-of-lipid-metabolism-a.gitbook.io/omics-data-visualization-in-r-and-python/metabolites-and-lipids-descriptive-statistical-analysis-in-r/basic-plotting-in-r/density-plots.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
