2016-04-01 5 views
0

Ich habe an einem Projekt gearbeitet, für die ich Spitzen und Täler in einem Datensatz (nicht nur die höchsten Zahlen pro Spalte, sondern alle Peaks und Täler). Ich schaffte es, es auf 1 Spalte zu arbeiten, aber ich verwende eine for-Schleife für das und ich muss dies für etwa 50 Spalten tun, also denke ich, ich sollte eine "Anwenden" -Funktion verwenden. Ich weiß einfach nicht, wie ich das machen soll. Kann ich "if" -Anweisungen und solche in einer "apply" -Funktion setzen?Verwenden Sie eine 'apply' Funktion, um Code mit bedingten Anweisungen in R

Hier ist, was ich für die Überprüfung einer Spalte verwendet: (‚First‘ ist der Name des Datensatzes und ‚Seq1‘ ist die erste Spalte)

Lowest = 0 
Highest = 0 
Summits = vector('numeric') 
Valleys = vector('numeric') 

for (i in 1:length(First$Seq1)) 
{ 
    if (!is.na(First$Seq1[i+1])) 
    { 
     if (First$Seq1[i] < Lowest) {Lowest = First$Seq1[i]} 
     if (First$Seq1[i] > Highest) {Highest = First$Seq1[i]} 

     if (First$Seq1[i] > 0 && First$Seq1[i+1] < 0) 
     { Summits <- append(Summits, Highest, after=length(Summits)) } 
     if (First$Seq1[i] < 0 && First$Seq1[i+1] > 0) 
     { Valleys <- append(Valleys, Lowest, after=length(Summits)) } 
    } 
} 

Antwort

0

Sicher Sie können! Ich würde zunächst eine Hilfsfunktion definieren, die definiert, was mit einer bestimmten Spalte zu tun ist, und dann rufen Sie diese Funktion innerhalb gelten:

HelperFun <- function(x) { 
    # your code from above, replacing 'Seq1' by x 
    } 
    apply(First, 2, HelperFun) 
+0

Ich habe eine Frage zu x. Was genau passiert damit? Wird es jedes Mal um 1 erhöht? Denn wenn ich Seq1 durch x ersetze, bekomme ich den Fehler, dass das x nicht existiert. –

+0

Ich habe es jetzt laufen! Vielen Dank! Das einzige, was ich jetzt herausfinden muss, ist, wie man die Ergebnisse am besten speichert. Ich musste 'function (x)' übrigens vor 'HelperFun' hinzufügen. Sollte jemand anderes es wissen wollen. –

+0

Sie sollten vor 'HelperFun' keine Funktion (x) hinzufügen müssen. Sie haben wahrscheinlich nicht ganz verstanden, wie "apply" funktioniert, da Sie etwas getan haben, was nicht notwendig sein sollte. – Roland

0

Eine *apply Funktion ist nicht besser für diese als eine for Schleife, vorausgesetzt, Sie don Wachsen Sie kein Objekt in der for Schleife. Sie dürfen niemals append in einer Schleife verwenden. Ordnen Sie Ihr Ergebnisobjekt vor und füllen Sie es aus.

Dies findet alle lokalen Minima auf einem Raster:

#an example 
set.seed(42) 
plane <- matrix(rnorm(100, sd = 5), 10) 

#plot 
library(raster) 
plot(raster(plane)) 

#initialize a logical matrix 
res <- matrix(TRUE, ncol = ncol(plane), nrow = nrow(plane)) 

#check for each subgrid of 2 times 2 cells which of the cells is the minimum 
for (i in 1:(nrow(plane) - 1)) { 
    for (j in 1:(ncol(plane) - 1)) { 
    inds <- as.matrix(expand.grid(r = i + 0:1, c = j + 0:1)) 
    #cell must be a minimum of all 4 subgrids it is part of 
    res[inds] <- res[inds] & plane[inds] == min(plane[inds]) 
    } 
} 

print(res) 
plane[res] 
#[1] -13.282277 -8.906542 -8.585043 -12.071038 -3.919195 -14.965450 -5.215595 -5.498904 -5.971644 -2.380870 -7.296070 

#highlight local minima 
plot(rasterToPolygons(raster(res)), border = t(res), add = TRUE) 

library(reshape2) 
res1 <- melt(res) 
res1 <- res1[res1$value,] 
text(x = res1$Var2 /10 - 0.05, 
    y = 1-res1$Var1 /10 + 0.05, 
    labels = round(plane[res],1)) 

resulting plot

ich hier angenommen habe, dass diagonale Nachbarn als Nachbarn gezählt und nicht nur Nachbarn in der gleichen Spalte oder Zeile. Aber das wäre trivial zu ändern.

+0

Problem mit der Definition der Ausgabe vor der Schleife ist, dass ich keine Ahnung habe, wie lange die Ausgabe sein wird. Es kann alles von 0 bis zu einem ziemlich hohen Wert sein. Ich könnte die Länge auf 1000 setzen, da ich nie so viele bekommen werde, aber dann werde ich oft den größten Teil des Arrays leer haben. Ich muss die Arrays wahrscheinlich später kürzen oder so ...? –

+0

Sicher. Mein Vorschlag ist, eine logische Matrix (siehe meinen Code) zurückzugeben, die für jeden Wert angibt, ob es ein lokales Minimum ist. Sie können dies verwenden, um Ihre Eingabematrix zu unterteilen, wenn Sie an den Werten selbst interessiert sind. – Roland

+0

Mein Datensatz ist eigentlich ganz anders als der, den Sie hier gezeigt haben. Ich habe 54 einzelne Videos für die Dunkelheit in einem bestimmten Gebiet analysiert. Ich betrachte dunkle Wellen, die über einen Vogelschwarm gehen. Deshalb suche ich nach hellen und dunklen Gipfeln. Ich bin mir nie sicher, wie weit (in der Zeit) diese Wellen auseinander liegen werden und ich kann daher nicht sehen, wie weit ich nach einem Maximum oder Minimum suchen muss. Das unterscheidet sich pro Video. –

0

Ich weiß, dass dies nicht die Lösung ist, die Sie wollen --- Sie haben eindimensionale Zeitreihen, aber hier ist eine (direktere) Variation von Rolands Lösung.

#example data 
set.seed(42) 
plane <- matrix(rnorm(100, sd = 5), 10) 
library(raster) 
r <- raster(plane) 

f <- focal(r, matrix(1,3,3), min, pad=TRUE, na.rm=TRUE) 
x <- r == f 
mins <- mask(r, x, maskvalue=FALSE) 

pts <- rasterToPoints(mins) 
cells <- cellFromXY(x, pts) 

r[cells] 

plot(r) 
text(mins, digits=1) 
plot(rasterToPolygons(mins), add=TRUE) 
Verwandte Themen