2016-05-26 17 views
8

Purtroppo, non ho trovato una soluzione da solo. Come creare un Manhattan plot all'interno di python usando, ad esempio, matplotlib/panda. Il problema è che in questi grafici l'asse x è discreto.Come creare una trama di Manhattan con matplotlib in python?

from pandas import DataFrame 
from scipy.stats import uniform 
from scipy.stats import randint 
import numpy as np 

# some sample data 
df = DataFrame({'gene' : ['gene-%i' % i for i in np.arange(1000)], 
'pvalue' : uniform.rvs(size=1000), 
'chromosome' : ['ch-%i' % i for i in randint.rvs(0,12,size=1000)]}) 

# -log_10(pvalue) 
df['minuslog10pvalue'] = -np.log10(df.pvalue) 
df = df.sort_values('chromosome') 

# How to plot gene vs. -log10(pvalue) and colour it by chromosome? 
+0

Si può solo modo sensato tracciare i dati numerici, non stringhe. Come sono realmente gli x-data? –

+0

Le trame di Manhattan sono molto comuni nella genetica e sono davvero piuttosto sensibili - o diciamo: informative - per i genetisti. I dati x sono solo nomi (sì, stringhe) di nomi SNP. (Forse avrei dovuto chiamare gli SNP x-data piuttosto che i geni nell'esempio.) –

+0

Non ho detto che i grafici di Manhattan non sono sensibili, ho detto che è in particolare impossibile calcolare in modo significativo stringhe e dati numerici. Devi in ​​qualche modo convertire i tuoi nomi in numeri, o semplicemente usare il loro indice. Fornirò un piccolo esempio utilizzando i dati artificiali come risposta di seguito. –

risposta

8

si può usare qualcosa di simile:

from pandas import DataFrame 
from scipy.stats import uniform 
from scipy.stats import randint 
import numpy as np 
import matplotlib.pyplot as plt 

# some sample data 
df = DataFrame({'gene' : ['gene-%i' % i for i in np.arange(10000)], 
'pvalue' : uniform.rvs(size=10000), 
'chromosome' : ['ch-%i' % i for i in randint.rvs(0,12,size=10000)]}) 

# -log_10(pvalue) 
df['minuslog10pvalue'] = -np.log10(df.pvalue) 
df.chromosome = df.chromosome.astype('category') 
df.chromosome = df.chromosome.cat.set_categories(['ch-%i' % i for i in range(12)], ordered=True) 
df = df.sort_values('chromosome') 

# How to plot gene vs. -log10(pvalue) and colour it by chromosome? 
df['ind'] = range(len(df)) 
df_grouped = df.groupby(('chromosome')) 

fig = plt.figure() 
ax = fig.add_subplot(111) 
colors = ['red','green','blue', 'yellow'] 
x_labels = [] 
x_labels_pos = [] 
for num, (name, group) in enumerate(df_grouped): 
    group.plot(kind='scatter', x='ind', y='minuslog10pvalue',color=colors[num % len(colors)], ax=ax) 
    x_labels.append(name) 
    x_labels_pos.append((group['ind'].iloc[-1] - (group['ind'].iloc[-1] - group['ind'].iloc[0])/2)) 
ax.set_xticks(x_labels_pos) 
ax.set_xticklabels(x_labels) 
ax.set_xlim([0, len(df)]) 
ax.set_ylim([0, 3.5]) 
ax.set_xlabel('Chromosome') 

Ho appena creato una colonna in più di correre dell'indice di avere il controllo sulla x etichette posizioni.

enter image description here

+0

Ho aggiunto le seguenti due righe appena prima di ordinare i valori in base al cromosoma: 'df.chromosome = df.chromosome.astype (' category '); df.chromosome = df.chromosome.cat.set_categories (['ch-% i'% i per i in range (12)], ordinato = True) '. Questo darà l'ordine corretto dei cromosomi sull'asse x e rende possibile che i cromosomi X e Y (non nell'esempio) appaiano alla fine. Forse puoi aggiornare il tuo esempio? Grazie! –

+0

Funziona bene quando il valore x è l'indice che assegni a ciascun modello di gene (che risponde alla domanda in modo +1), ma che dire di quando il tuo valore x è in realtà un insieme di coordinate genomiche rappresentate come numeri interi. In questo caso, non vi è alcuna garanzia che gli interi siano sequenziali o univoci come nel tuo esempio con gli indici. Quando sostituisco gli indici con le coordinate genomiche, tutti i miei cromosomi sono sovrapposti anziché affiancati. – Malonge

7
import matplotlib.pyplot als plt 
from numpy.random import randn, random_sample 

g = random_sample(int(1e5))*10 # uniform random values between 0 and 10 
p = abs(randn(int(1e5))) # abs of normally distributed data 

""" 
plot g vs p in groups with different colors 
colors are cycled automatically by matplotlib 
use another colormap or define own colors for a different cycle 
""" 
for i in range(1,11): 
    plt.plot(g[abs(g-i)<1], p[abs(g-i)<1], ls='', marker='.') 

plt.show() 

Example of a manhattan style plot

Si può anche verificare this script, che sembra offrire una soluzione completa al problema.

+0

Bello! Sono ancora nuovo nel chiamare la funzione di trama all'interno di un ciclo. Semplicemente non ci avrei pensato. Come aggiungerei sotto ogni colonna colorata il nome del cromosoma rispettato? Ogni colonna ha una larghezza diversa, poiché ciascun cromosoma ha una lunghezza diversa. Vedere l'esempio nella pagina di wikipedia (https://upload.wikimedia.org/wikipedia/commons/1/12/Manhattan_Plot.png). –

+0

In matplotlib è possibile impostare le proprietà dell'etichetta per l'asse xe anche fornire le proprie stringhe per stampare anziché le etichette numeriche ... Aspetta, ora capisco. Vuoi davvero tratteggiare il cromosoma contro il valore di pvalue e non il gene. Ma il coor è fondamentalmente anche solo il numero cromosomico. Da dove viene il numero del gene? –

+0

Quello che ancora non capisco è come i dati cromosomici dovrebbero essere distribuiti sull'asse x, perché è, come hai detto tu, discreto. –