2016-05-31 3 views
1

Ich suche nach einem Allzweck-Algorithmus, um kurze numerische Reihen aus Listen mit einer maximalen Länge von ein paar hundert Zahlen zu identifizieren. Dies wird verwendet, um Massenreihen von Massenspektrometriedaten (ms1) zu identifizieren.Gibt es einen allgemeinen Algorithmus, um eine numerische Reihe zu identifizieren?

Zum Beispiel angesichts der folgenden Liste, würde ich identifizieren möchte, dass drei dieser Zahlen passen die Reihe N + 1, N + 2, usw.

426.24 <= N 
427.24 <= N + 1/x 
371.10 
428.24 <= N + 2/x 
851.47 
451.16 

Die Serie sind alle das Format: N, N + 1/x, N + 2/x, N + 3/x, N + 4/x usw., wobei x eine ganze Zahl ist (im Beispiel x = 1). Ich denke, diese Einschränkung macht das Problem sehr handhabbar. Irgendwelche Vorschläge für einen schnellen/effizienten Weg, dies in R zu lösen?

+1

Ich glaube nicht, dass dies eine Frage ist. Wenn Sie einen Algorithmus haben und wissen möchten, wie Sie effizient in R implementieren können, dann wäre es sinnvoll. Wie auch immer, kennst du N? Sie können N von allen Werten subtrahieren. Auch ist nicht klar, was ist die Voraussetzung? –

+0

N kann empirisch als die erste Nummer der Reihe bestimmt werden. N von allen Werten zu subtrahieren und dann nach doppelten Werten zu suchen, ist eigentlich eine ziemlich gute Lösung. –

+0

In diesem Beispiel wäre es ziemlich offensichtlich, wenn Sie "diff (sort (x))" betrachtet hätten. Aber das würde nicht so gut funktionieren, wenn andere Werte mit den Serienwerten überlappen würden. – Gregor

Antwort

2

Diese Routine erzeugt Reihen mit x von 1 bis 10 (Sie könnten sie erhöhen). Und überprüft, wie viele in der ursprünglichen Liste der Nummern enthalten sind.

N = c(426.24,427.24,371.1,428.24,851.24,451.16) 
N0 = N[1] 
x = list(1,2,3,4,5,6,7,8,9,10) 
L = 20 

Series = lapply(x, function(x){seq(from = N0, by = 1/x,length.out = L)}) 
countCoincidences = lapply(Series, function(x){sum(x %in% N)}) 

Ergebnis:

unlist(countCoincidences) 
[1] 3 3 3 3 3 3 3 3 3 2 

Wie Sie sehen können, mit x = 1 3 Zufälle haben. Dasselbe gilt für alle x bis x = 9. Hier müssen Sie entscheiden, welches x das gewünschte ist.

+0

Ich ging mit diesem Ansatz, weil es einfacher war, und ich konnte leicht für +/- experimentellen Fehler überprüfen. –

2

Da Sie eine arithmetische Sequenz suchen, ist der Unterschied k konstant. Sie können also den Vektor überfahren und jeden Wert von der Sequenz subtrahieren. Wenn Sie eine Sequenz haben, ergibt das Subtrahieren des zweiten Terms vom Vektor Werte von -k, 0 und k, so dass Sie die Sequenz finden können, indem Sie nach Übereinstimmungen zwischen Vektor - Wert und seinem Gegenteil suchen, Wert - vector:

x <- c(426.24, 427.24, 371.1, 428.24, 851.47, 451.16) 

unique(lapply(x, function(y){ 
    s <- (x - y) %in% (y - x); 
    if(sum(s) > 1){x[s]} 
})) 

# [[1]] 
# NULL 
# 
# [[2]] 
# [1] 426.24 427.24 428.24 
+0

Dieser Ansatz ist wirklich nett. Allerdings muss ich einige Anpassungen vornehmen, um experimentellen Fehler (bis ~ 10ppm) zu berücksichtigen. Dieser radikal vereinfachte Ansatz lässt mich nicht wirklich damit umgehen. Ich muss darüber nachdenken, wie ich es modifizieren kann. –

+0

Der einfachste Weg ist wahrscheinlich die Verwendung von "rund", z. 's <- rund (x - y, 1)% in% Runde (y - x, 1)', wenn das genau genug ist. – alistaire

Verwandte Themen