> For the complete documentation index, see [llms.txt](https://igb.mit.edu/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://igb.mit.edu/mini-courses/python/data-processing-with-python/seaborn/visualizing-rnaseq-data.md).

# Visualizing RNAseq Data

### Getting Started

```
import pandas as pd
import numpy as np
import seaborn as sns
import glob
import matplotlib.pyplot as plt
sns.set_context('paper')
sns.set_style("whitegrid")
```

### Volcano Plot

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FVP4FsU6WjVgjn71Zpc8Z%2Fimage.png?alt=media&amp;token=3b86ef5e-3e07-4e23-bd6f-f4540afbdb50" alt=""><figcaption></figcaption></figure>

This is what we aim to reproduce basing on the file volcano\_data.tsv. Let's read the volcano\_data.tsv file into a pandas dataframe. `glob.glob('C:\\Users\duan\Desktop\PythonDataProcessingVisualization\*.tsv') # get a list of files in your directory ending in .tsv`

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FX75OncvRTJaFT02sMjVg%2Fimage.png?alt=media&amp;token=69c2bc8f-e386-4032-847c-95a719a584b8" alt=""><figcaption></figcaption></figure>

```
vol = pd.read_csv('C:\\Users\\duan\\Desktop\\PythonDataProcessingVisualization\\KOvsWTdiffExp.tsv', sep='\t')
```

inspect the 'head' of the file

```
vol.head()
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2F9lP53baxtMnaa4pm0cdC%2Fimage.png?alt=media&amp;token=ed397ec7-e7ce-4a73-a328-b6a6a96fed41" alt=""><figcaption></figcaption></figure>

```
vol.shape
```

(4900, 6)

Notice that the qvalues in the file need to be log-transformed to match the figure Create a new column in the vol dataframe where 'log10\_q' = -log\_base\_10(qval) for each gene...the numpy function np.log10 is helpful

```
vol['log10_q'] = -np.log10(vol['padj']) #calculate the -log2 of qvalues
```

output a summary of the data (use the .describe() function)

```
vol.describe()
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FDzScozDW4jIE5NpMYwpx%2Fimage.png?alt=media&amp;token=ad5a1111-ee30-4b63-baf5-f139cb55a804" alt=""><figcaption></figcaption></figure>

We want to plot and color the genes that increase in knockout, decrease with knockout, and show no significant change (q-val > 0.05). Let's categorize our data

create a new column called 'data\_category' with entires 'increases in Knockout', 'decreases in Knockout', and 'not significant' set these values appropriately for each gene hint - inspect the 'log2FoldChange' value or the 'padj' fields to determine each case

```
sns.scatterplot(data=vol, y='log10_q', x='log2FoldChange', hue='data_category', legend='brief',
                palette={'not significant':'grey', 'increases in Knockout':"red", 'decreases in Knockout':"blue"}, 
                edgecolor='grey',s=80, linewidth=0.25)
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2F1QswGhv140pJslEPhVWv%2Fimage.png?alt=media&amp;token=debe4a8d-966c-4ecc-8b64-35222d9874ce" alt=""><figcaption></figcaption></figure>

save a list of the significant genes and their qvalues (any gene\_ids with qval<0.05), and output this list to a .csv file

```
sig_genes = vol.loc[vol['padj']<.05, ['geneID', 'padj', 'log2FoldChange']]
sig_genes.shape
```

(2582, 3)

```
sig_genes.head(8)
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FFx4nwdn1g1vsnqHGRXQb%2Fimage.png?alt=media&amp;token=607b5f4c-76da-4b60-a243-a263f3d7cd50" alt=""><figcaption></figcaption></figure>

Save significant genes to a csv file

```
sig_genes.to_csv('C:\\Users\duan\Desktop\PythonDataProcessingVisualization\significant_hits.csv')
```

### Heatmap

Next, we are going to reproduce a heatmap below. This clustered heat map aims to show groups of genes whose transcript levels are coordinated across age or mutant background

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FT1tEBZlEsUDYk0v5rJpJ%2Fimage.png?alt=media&amp;token=074d22aa-162a-4838-ac67-020e6dde3598" alt=""><figcaption></figcaption></figure>

The plotting will be based on rpkm.tsv which contains \~600 significant genes we want to inspect.

read in the 'rpkm.tsv' file as a pandas dataframe, save it as dataset

```
dataset = pd.read_csv('C:\\Users\duan\Desktop\PythonDataProcessingVisualization\\rpkm.tsv', sep='\t')
```

briefly inspect the dataframe for shape, general entries, and summary statistics

```
dataset.shape
```

(600,7)

```
dataset.head()
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2F2tlVgm3d0fYVwUe9qj1p%2Fimage.png?alt=media&amp;token=0b34b7bb-2394-45d4-bcc0-670a24bd44c9" alt=""><figcaption></figcaption></figure>

```
dataset.describe()
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FGcGPAjcsSkUDhQEE8Hsv%2Fimage.png?alt=media&amp;token=1d5fbfbe-2a43-434a-803e-14911849f563" alt=""><figcaption></figcaption></figure>

People often plot using 'row median centered' each gene This means they divided each row by the median value across that entire row. They also log-transformed that result

Calculate the median value for each gene (row)

```
row_medians = dataset.median(axis=1,numeric_only=True)
```

Now create a copy of the dataset, and save it as dataset\_row\_norm Row median center and log2-transform each gene in dataset\_row\_norm

```
dataset_row_norm = dataset.copy() #make a copy of the dataset so we can manipulate it
for col in dataset.columns[1:]:
    dataset_row_norm[col] = np.log2((dataset[col]+0.1)/(row_medians+0.1))
```

look at the summary statistics now Also, look at a few random gene rows and make sure the result in sensible Finally, look at the .head() to see how it is indexed

```
dataset_row_norm.describe()
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2F3mZJVQlUwDwLXMp1klox%2Fimage.png?alt=media&amp;token=780bedcf-3a0b-4dd4-9fd4-1ba212eb32e2" alt=""><figcaption></figcaption></figure>

```
dataset_row_norm.iloc[200,1:].median() #test some random rows, make sure the median value is 0
```

-0.04326176484815142

```
dataset_row_norm.head()
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2F8vRQs23nutD9knJa4kIF%2Fimage.png?alt=media&amp;token=fb900fc6-bec3-47c7-89b4-e87fd2314bbf" alt=""><figcaption></figcaption></figure>

change the indexing to use the gene name instead of the row number

```
dataset_row_norm = dataset_row_norm.set_index('geneID')
```

Now let's plot the full dataset. Use seaborn clustermap to generate a heat map and cluster each row. Look at the seaborn clustermap documentation to figure out what arguments to pass

```
import fastcluster
```

```
sns.clustermap(dataset_row_norm, row_cluster=True, col_cluster=False, cmap="RdBu_r", figsize=(10,10))
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2Fgrk1WBW2BHv5ZMPXLA4Q%2Fimage.png?alt=media&amp;token=7da81e89-423d-41c1-98b9-2645901a0dbd" alt=""><figcaption></figcaption></figure>

### Another Example

sometimes you need additional work to make a nice heatmap. See the example below:

Read in the example data

```
dataset = pd.read_csv('C:\\Users\duan\Desktop\PythonDataProcessingVisualization\\TPM_reads_raw.tsv', sep='\t')
```

Examine the data

```
dataset.shape
```

(5823, 36)

```
dataset.head()
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FHkew7eMvtz8qyvLR1KNk%2Fimage.png?alt=media&amp;token=bb840a2f-9edc-4a5e-ba9c-18547dc04f1e" alt=""><figcaption></figcaption></figure>

```
dataset.describe()
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2Fu8eaApISFKC4SgmSnm7p%2Fimage.png?alt=media&amp;token=43c14df0-595d-455e-818b-c93129603e93" alt=""><figcaption></figcaption></figure>

\
Prepare the data for heatmap plotting

```
row_medians = dataset.median(axis=1,numeric_only=True) #calculate the median of each row
dataset_row_norm = dataset.copy() #make a copy of the dataset so we can manipulate it
for col in dataset.columns[1:]:
    dataset_row_norm[col] = np.log2((dataset[col]+0.1)/(row_medians+0.1))
dataset_row_norm = dataset_row_norm.set_index('gene')
```

Heatmap plotting

```
sns.clustermap(dataset_row_norm, row_cluster=True, col_cluster=False, cmap="RdBu_r", figsize=(10,10))
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FuoWKMyP6Xoi1P3XxqfXl%2Fimage.png?alt=media&amp;token=23de18fa-5cda-4d62-b050-c7c4c933f46d" alt=""><figcaption></figcaption></figure>

It is necessary to 'zoom' in on the genes that showed significant changes. Sometimes people 'capped' their fold changes at -1.5 and +1.5, we'll do the same.

Start by copying our row-normalized dataframe to a new dataframe and setting all values greater than 1.5 to 1.5, and all less than -1.5 to -1.5 Save this as capped\_row\_norm\_dataset

```
capped_row_norm_dataset = dataset_row_norm.copy()
capped_row_norm_dataset[capped_row_norm_dataset>1.5] = 1.5
capped_row_norm_dataset[capped_row_norm_dataset<-1.5] = -1.5
```

Look at the summary statistics to see if this worked

```
Look at the summary statistics to see if this worked
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2F9azmMy2WpY81SKul8hru%2Fimage.png?alt=media&amp;token=b0bb7970-45ea-4a68-92fa-db28ccaffbf5" alt=""><figcaption></figcaption></figure>

Read volcano plot file

```
vol = pd.read_csv('C:\\Users\\duan\\Desktop\\PythonDataProcessingVisualization\\volcano_data.tsv', sep='\t')
```

Inspect volcano plot file

```
vol.head()
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2F95x7Dpr09S47szcsc1sq%2Fimage.png?alt=media&amp;token=0723b2be-f197-46bd-a5d6-6b99567b4aa6" alt=""><figcaption></figcaption></figure>

```
vol.shape
```

(13547, 4)

Prepare for volcano plotting

```
vol['log10_q'] = -np.log10(vol['qval']) #calculate the -log2 of qvalues
```

```
vol.describe()
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FhhNb25IY8WOXQiXkLfHb%2Fimage.png?alt=media&amp;token=9d294a1d-a8c8-4e7a-8248-e07dca9d3876" alt=""><figcaption></figcaption></figure>

```
vol.loc[vol['log2foldchange']>0,'data_category'] = 'increases with age'
vol.loc[vol['log2foldchange']<0,'data_category'] = 'decreases with age'
vol.loc[vol['qval']>0.05,'data_category'] = 'not significant'
```

Volcano plotting

```
sns.scatterplot(data=vol, y='log10_q', x='log2foldchange', hue='data_category', legend='brief',
                palette={'not significant':'grey', 'increases with age':"red", 'decreases with age':"blue"}, 
                edgecolor='grey',s=80, linewidth=0.25)
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FpqmQ2I7VZNDwxPjWBDb3%2Fimage.png?alt=media&amp;token=bd9f43a2-d71b-433b-8866-11ee9f56d616" alt=""><figcaption></figcaption></figure>

Identify significant genes

```
sig_genes = vol.loc[vol['qval']<.05, ['gene_id', 'qval', 'log2foldchange']]
```

Now we need to just pull out the genes that show significant age-dependence Make a list of all the gene names that are in both dataset\_row\_norm and the list of significant genes (sig\_genes) from above. Save this list as genes\_to\_cluster

```
#get the genenames that are the same between the datasets
genes_to_cluster = [gene for gene in capped_row_norm_dataset.index if gene in sig_genes.values] 
```

use the .loc function to pull out just the rows of genes we want to cluster, and see how many genes that is

```
capped_row_norm_dataset.loc[genes_to_cluster, :].shape
```

(1731, 35)

Almost there - now make your heatmap!

```
sns.clustermap(capped_row_norm_dataset.loc[genes_to_cluster, :], row_cluster=True, col_cluster=False, cmap="RdBu_r", figsize=(8,8))
```

<figure><img src="https://498238201-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FWuHhstIreJ3jFvE4gQ3y%2Fuploads%2FpFPt4iyWmOE71mtNh7vf%2Fimage.png?alt=media&amp;token=d0ecab89-42f8-4e1b-a5ba-425d70b9aa1c" alt=""><figcaption></figcaption></figure>
