2017-03-13 3 views
2

Bei dieser Frage suche ich nicht gerade nach einem Tal, sondern nach einer Möglichkeit, die sich wiederholenden "Täler" in der Zahlenfolge zu identifizieren."Täler" in einer Zahlenfolge finden

Ich habe diese Daten

x <- c(1,1,2,2,1,1,2,2,3,3,3,2,2,2,3) 

so habe ich versucht, die folgenden:

test <- data.frame(x) 

test <- test %>% mutate(Lag = c(tail(x, -1), NA)) 

which(test$x > test$Lag)+1 

, die mir die Positionen von 5 saldiert und 12.

Die Frage ist, wie kann ich Erhalte den Code, um die verbleibenden "Täler" in der Zahlenfolge zu identifizieren. Erwartete Ausgabe ist, Positionen von 5, 6 und 12, 13, 14 zu identifizieren.

Es ist etwas ähnlich zu den lokalen Minima in Zeitreihen, aber das ist nicht, was ich suche.

Ich möchte auch diese als Blöcke identifizieren; wie Positionen von 5, 6 als zur Kategorie 1 und 12, 13, 14 als zur Kategorie 2 gehörend.

Vielen Dank im Voraus!

Antwort

1

Wir können dies auch mit rle von base R

v1 <- seq_along(x)*inverse.rle(within.list(rle(x), 
     {i1 <- c(0, diff(values))<0; values <- i1})) 
v1[v1!=0] 
#[1] 5 6 12 13 14 
+1

Es ist besser, 'c (0, Diff (Werte)) <0 'in' c (0, Diff (Werte)) <0 & c (Diff (Werte, Differenzen = 2), 0) <0 zu ändern '. Ersteres bedeutet eine Stufe, und letzteres bedeutet ein Tal. Aber beide funktionieren gut mit den Beispieldaten. – Feng

+0

hat Ihre Lösung unterstützt, da es sich um ein Szenario wie '' 'x <- c (1,1,2,2,2,1,1,1,2,2,2,1,1,1,3,3) handelte , 3,1,1,1,2,2,2,1,1,1 '' '. versteht deinen Code aber nicht ... welcher Art von Logik folgt der Code? und wie kommt Fengs Lösung ins Spiel? – bzzbzzRzzbzz

+1

@bzzbzzRzzbzz Die 'rle' gibt eine' liste' von 'Werten' und' length' für die angrenzenden Werte, die gleich sind. . was wir getan haben, war die Differenz von "Werten" zu nehmen, überprüfen, ob es kleiner als 0 ist, um den Index von lokalen Minima zu finden und diese dann 'Werten' zuzuweisen, so dass alle anderen Werte FALSCH sind und nur diejenigen, die die Bedingungen erfüllen WAHR. Wenn wir mit der Folge von 'x' multiplizieren, ('seq_along (x)'), wird die FALSE zu 0 und anderen 1) gezwungen, was zu einem Vektor von 0; s und Sequenzindex führt. THen, wir unterteilen die Werte, die nicht 0 sind ('v1 [v1! = 0]') – akrun

2

Dies kann unter Verwendung von cummax gelöst werden. Arbeiten mit Ihrem x,

cummax(x) 
# [1] 1 1 2 2 2 2 2 2 3 3 3 3 3 3 3 
which(x != cummax(x)) 
# [1] 5 6 12 13 14 
x[x != cummax(x)] 
# [1] 1 1 2 2 2 

Sie sind 5-6 und 12-14, gegeben und dann wissen Sie, jede welchen Kategorien zugeordnet ist. Sie können sie vielleicht sinnvoller gruppieren mit split oder einige Binning-Funktion.

1

Wir haben es mit regulären Ausdrücken tun könnte (Tal bedeutet ein negative slope von 0 slopes von einem positive slope in x gefolgt gefolgt, unter der Annahme, dass die Pisten sind -1, 0 und 1 wie in den Eingabedaten, aber wir können verallgemeinern):

pattern <- 'N([0]+)P' # \_.._/ 
txt <- gsub('1', 'P', gsub('-1', 'N', paste(diff(x), collapse=''))) 
matched <- gregexpr(pattern,txt) 
positions <- unlist(matched) + 1 
lengths <- attr(matched[[1]], "match.length") - 2 # exclude N & P 
valley.points <- lapply(1:length(positions), function(i)seq(positions[i], positions[i]+lengths[i],1)) 

#[[1]] 
#[1] 5 6 

#[[2]] 
#[1] 12 13 14 

plot(x, type='l') 
points(unlist(valley.points), x[unlist(valley.points)], pch=19, col='red') 

enter image description here

+1

Interessanter Ansatz, ich hätte nicht gedacht, textliche reguläre Ausdrücke für die numerische Analyse zu verwenden . Kreativ! – r2evans

Verwandte Themen