Jeśli dobrze rozumiem pytanie, chcesz wykryć, kiedy h_no
nie wzrasta, a następnie zwiększyć class
. (Zamierzam przejść przez, jak rozwiązałem ten problem, na końcu jest niezależna funkcja.)
Pracujący
Na razie zależy nam tylko na h_no
kolumnie, więc możemy ją wyodrębnić z ramki danych:
> h_no <- data$h_no
Chcemy wykryć, kiedy h_no
nie rośnie, co możemy zrobić, obliczając, kiedy różnica między kolejnymi elementami jest ujemna lub zerowa. R zapewnia diff
funkcję, która daje nam wektor różnic:
> d.h_no <- diff(h_no)
> d.h_no
[1] 1 1 1 -3 1 1 1 1 1 1 -6 1 1 1
Gdy już to zrobimy, łatwo jest znaleźć te, które nie są pozytywne:
> nonpos <- d.h_no <= 0
> nonpos
[1] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
[13] FALSE FALSE
W R TRUE
i FALSE
są w zasadzie takie same jak 1
i 0
, więc jeśli otrzymamy skumulowaną sumę nonpos
, wzrośnie o 1 w (prawie) odpowiednich miejscach. cumsum
Funkcja (który jest w zasadzie przeciwieństwem diff
) może to zrobić.
> cumsum(nonpos)
[1] 0 0 0 1 1 1 1 1 1 1 2 2 2 2
Ale są dwa problemy: liczby są o jeden za małe; i brakuje nam pierwszego elementu (w pierwszej klasie powinny być cztery).
Pierwszym problemem jest po prostu rozwiązany: 1+cumsum(nonpos)
. A drugi wymaga tylko dodania a 1
na początku wektora, ponieważ pierwszy element jest zawsze w klasie 1
:
> classes <- c(1, 1 + cumsum(nonpos))
> classes
[1] 1 1 1 1 2 2 2 2 2 2 2 3 3 3 3
Teraz możemy dołączyć go z powrotem do naszej ramki danych za pomocą cbind
(używając class=
składni, możemy nadać kolumnie class
nagłówek):
> data_w_classes <- cbind(data, class=classes)
A data_w_classes
teraz zawiera wynik.
Ostateczny wynik
Możemy skompresować linie razem i zawinąć je w funkcję, aby była łatwiejsza w użyciu:
classify <- function(data) {
cbind(data, class=c(1, 1 + cumsum(diff(data$h_no) <= 0)))
}
Lub, ponieważ ma sens, class
aby był czynnikiem:
classify <- function(data) {
cbind(data, class=factor(c(1, 1 + cumsum(diff(data$h_no) <= 0))))
}
Używasz dowolnej funkcji, takiej jak:
> classified <- classify(data) # doesn't overwrite data
> data <- classify(data) # data now has the "class" column
(Ta metoda rozwiązania tego problemu jest dobra, ponieważ unika jawnej iteracji, która jest ogólnie zalecana dla R, i unika generowania wielu wektorów pośrednich i list itp. A także całkiem fajne, jak można to zapisać w jednej linii :))