Come cercare le valli in un grafico?


10

Sto esaminando alcuni dati di copertura genomica che è fondamentalmente un lungo elenco (alcuni milioni di valori) di numeri interi, ognuno dei quali dice quanto bene (o "in profondità") sia coperta questa posizione nel genoma.

Vorrei cercare "valli" in questi dati, cioè regioni che sono significativamente "più basse" del loro ambiente circostante.

Nota che la dimensione delle valli che sto cercando può variare da 50 basi a poche migliaia.

Che tipo di paradigmi consiglieresti di usare per trovare quelle valli?

AGGIORNARE

Alcuni esempi grafici per i dati: testo alternativo testo alternativo

AGGIORNAMENTO 2

Definire cos'è una valle è ovviamente una delle domande con cui sto lottando. Questi sono ovvi per me: testo alternativo testo alternativo

ma ci sono alcune situazioni più complesse. In generale, ci sono 3 criteri che prendo in considerazione: 1. La copertura (media? Massima?) Nella finestra rispetto alla media globale. 2. La (...) copertura nella finestra rispetto all'ambiente circostante. 3. Quanto è grande la finestra: se vedo una copertura molto bassa per un breve periodo è interessante, se vedo una copertura molto bassa per un lungo periodo è anche interessante, se vedo una copertura leggermente bassa per un breve periodo non è davvero interessante , ma se vedo una copertura leggermente bassa per un lungo arco di tempo, lo è ... Quindi è una combinazione della lunghezza del sapn e della sua copertura. Più è lungo, più alto lascio che la copertura sia e la considero ancora una valle.

Grazie,

Dave


Potresti fornire un piccolo campione di dati?
Shane,

@Shane vedi aggiornamento
David B

@ Grazie David. Come implicano entrambe le risposte, qui è possibile applicare l'analisi delle serie storiche poiché sono state ordinate osservazioni.
Shane,

È difficile rispondere senza sapere esattamente cosa stai cercando. Puoi forse fare un cerchio intorno ai punti sulle trame che stai cercando di catturare? Cosa consideri una "valle"? quanto in basso deve andare e cosa stai cercando di tornare? È difficile formulare una soluzione senza conoscere la domanda, ovvero soglie e simili.
Falmarri,

@ Shane ♦ Grazie. Dato che non ho esperienza con l'analisi delle serie temporali, potresti lasciare alcuni suggerimenti su dove dovrei iniziare?
David B,

Risposte:


5

È possibile utilizzare una sorta di approccio Monte Carlo, ad esempio utilizzando la media mobile dei dati.

Prendi una media mobile dei dati, usando una finestra di dimensioni ragionevoli (immagino che dipenda da te decidere quanto largo).

I dati nei tuoi dati saranno (ovviamente) caratterizzati da una media inferiore, quindi ora devi trovare una "soglia" per definire "bassa".

Per fare ciò, scambia casualmente i valori dei tuoi dati (ad es. Utilizzando sample()) e ricalcola la media mobile per i tuoi dati scambiati.

Ripeti l'ultimo passaggio un numero ragionevolmente elevato di volte (> 5000) e memorizza tutte le medie di queste prove. Quindi essenzialmente avrai una matrice con 5000 linee, una per prova, ognuna contenente la media mobile per quella prova.

A questo punto per ogni colonna scegli il quantile 5% (o 1% o quello che vuoi), ovvero il valore sotto il quale si trova solo il 5% della media dei dati randomizzati.

Ora hai un "limite di confidenza" (non sono sicuro che sia il termine statistico corretto) con cui confrontare i tuoi dati originali. Se trovi una parte dei tuoi dati inferiore a questo limite, puoi chiamarla a through.

Naturalmente, tieni presente che non questo né nessun altro metodo matematico potrebbe mai darti alcuna indicazione di significato biologico, anche se sono sicuro che tu ne sia ben consapevole.

EDIT - un esempio

require(ares) # for the ma (moving average) function

# Some data with peaks and throughs 
values <- cos(0.12 * 1:100) + 0.3 * rnorm(100) 
plot(values, t="l")

# Calculate the moving average with a window of 10 points 
mov.avg <- ma(values, 1, 10, FALSE)

numSwaps <- 1000    
mov.avg.swp <- matrix(0, nrow=numSwaps, ncol=length(mov.avg))

# The swapping may take a while, so we display a progress bar 
prog <- txtProgressBar(0, numSwaps, style=3)

for (i in 1:numSwaps)
{
# Swap the data
val.swp <- sample(values)
# Calculate the moving average
mov.avg.swp[i,] <- ma(val.swp, 1, 10, FALSE)
setTxtProgressBar(prog, i)
}

# Now find the 1% and 5% quantiles for each column
limits.1 <- apply(mov.avg.swp, 2, quantile, 0.01, na.rm=T)
limits.5 <- apply(mov.avg.swp, 2, quantile, 0.05, na.rm=T)

# Plot the limits
points(limits.5, t="l", col="orange", lwd=2)
points(limits.1, t="l", col="red", lwd=2)

Questo ti consentirà solo di trovare graficamente le regioni, ma puoi trovarle facilmente usando qualcosa sulle linee di which(values>limits.5).


Ovviamente puoi applicare lo stesso approccio usando qualcos'altro rispetto alla media mobile, questo era solo per dare un'idea.
nico,

+1 Grazie mille, nico. Fammi vedere se ti ho capito bene: alla fine, questo è fondamentalmente come impostare una soglia globale e definire qualsiasi punto con valore <soglia come parte di una valle. Il campionamento ecc. Viene usato solo per ottenere una misura significativa (quantile) per impostare la soglia. Perché non possiamo usare una sola soglia per tutti i punti, intendo, se avessimo fatto abbastanza simulazioni avremmo ottenuto linee rette (leggere e gialle). Inoltre, correggimi se sbaglio, ma questo non tiene conto dell'ambiente circostante ma esamina il valore assoluto di ogni punto.
David B,

@ David B: ovviamente, potresti usare una soglia globale e questo probabilmente ti farebbe risparmiare un po 'di tempo di calcolo. Immagino che scegliere qualcosa come 1/3 della media globale potrebbe essere un inizio. Questo processo di scambio è probabilmente più utile se si utilizzano altre statistiche rispetto alla media mobile, principalmente per dare un'idea. Comunque la media mobile terrà conto dell'ambiente circostante, nell'esempio prenderà in considerazione una finestra di 10 punti.
nico,

4

Sono completamente all'oscuro di questi dati, ma supponendo che i dati siano ordinati (non in tempo, ma per posizione?) Ha senso fare uso dei metodi delle serie temporali. Esistono molti metodi per identificare i cluster temporali nei dati. Generalmente vengono utilizzati per trovare valori elevati, ma possono essere utilizzati per valori bassi raggruppati insieme. Sto pensando qui a statistiche di scansione, statistiche di somma cumulativa (e altre) utilizzate per rilevare epidemie di malattia nei dati di conteggio. Esempi di questi metodi sono nel pacchetto di sorveglianza e nel pacchetto DCluster.


@cxr Grazie per la tua risposta. Ho dato un'occhiata surveillancee DCluster , ma potresti per favore essere un po 'più specifico? Sono entrambi pacchetti relativamente grandi e il loro obiettivo sembra abbastanza specifico. Non sono sicuro da dove cominciare.
David B,

2

Ci sono molte opzioni per questo, ma una buona: puoi usare la msExtremafunzione nel msProcesspacchetto .

Modificare:

Nell'analisi delle prestazioni finanziarie, questo tipo di analisi viene spesso eseguita utilizzando un concetto di "drawdown". Il PerformanceAnalyticspacchetto ha alcune utili funzioni per trovare queste valli . Puoi usare lo stesso algoritmo qui se tratti le tue osservazioni come una serie temporale.

Ecco alcuni esempi di come potresti essere in grado di applicare questo ai tuoi dati (dove le "date" sono irrilevanti ma utilizzate solo per l'ordinamento), ma i primi elementi zoonell'oggetto sarebbero i tuoi dati:

library(PerformanceAnalytics)
x <- zoo(cumsum(rnorm(50)), as.Date(1:50))
findDrawdowns(x)
table.Drawdowns(x)
chart.Drawdown(x)

Grazie Shane, ma questo sembra trovare minimi locali (o massimi) - cioè un singolo punto in una regione. I miei dati (come qualsiasi altro dato biologico) SONO RUMOROSI> Non mi interessa davvero i minimi punti ma le regioni più grandi che sono basse.
David B,

Se hai punti locali massimi e minimi, puoi facilmente calcolare le differenze. Quindi vuoi sapere casi in cui le differenze sono sia di ampiezza che di "durata"? Questi dati sono serie temporali?
Shane,

@david Forse puoi usare iterativamente questa funzione. Utilizzare la funzione per identificare un minimo. Rilascia quel punto e i punti circostanti (dì x punti entro un certo livello di tolleranza). È possibile scegliere un livello di tolleranza (ad es. + - 10 conteggi) che definirebbe una regione piatta per l'applicazione. Trova un nuovo minimo nel nuovo set di dati. Funzionerà?

@shane L'analogia che mi viene in mente è quella delle valli in una regione montuosa. Penso che l'obiettivo sia quello di identificare tutte le valli e il problema è che alcune valli sono "più profonde" e alcune sono "poco profonde" rispetto alle montagne.

@Shane Non è una serie temporale, queste sono coordinate lungo il genoma (cromosoma).
David B,

2

Alcuni pacchetti del bioconduttore (ad es. ShortRead , Biostrings , BSgenome , IRanges , genomeIntervals ) offrono servizi per gestire posizioni del genoma o vettori di copertura, ad es. Per ChIP-seq e identificare regioni arricchite. Per quanto riguarda le altre risposte, concordo sul fatto che qualsiasi metodo basato su osservazioni ordinate con un filtro basato sulla soglia consentirebbe di isolare il segnale basso all'interno di una banda specifica.

Forse puoi anche guardare i metodi usati per identificare le cosiddette "isole"

Zang, C, Schones, DE, Zeng, C, Cui, K, Zhao, K e Peng, W (2009). Un approccio di clustering per l'identificazione di domini arricchiti dai dati ChIP-Seq di modifica dell'istone . Bioinformatica, 25 (15) , 1952-1958.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.