Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using functionals instead of for loops to identify sequential changes in a vector

Tags:

r

My data look like this:

enter image description here

I want to identify which "downward trend" each observation is part of, so I can group them and do things like make this graph:

enter image description here

My logic for distinguishing "downward trends" is that they end when the next observation has a higher measurement.

I've written a loop to do this, but I'm wondering if there's a better way to do it with one of the apply functions or something like them.

##Create sample data
df <- data.frame(timestamp = seq(1:20),
                 measurement = seq(10, 1, by = -1))


## This is the for loop I'm hoping to improve
df$downward.trend.seq <- 0
seq <- 1
for(i in 1:nrow(df)){

  df$downward.trend.seq[i] <- seq

  if (i < nrow(df) & df$measurement[i] < df$measurement[i+1]) {
    seq <- seq + 1
  }

}


## Code for plots
library(ggplot2)
library(dplyr)
ggplot(df, aes(x = timestamp, y = measurement)) + geom_point()
ggplot(df, aes(x = timestamp, y = measurement, group = downward.trend.seq)) + geom_line(aes(color=downward.trend.seq %>% factor))
like image 616
Thalecress Avatar asked Jan 10 '16 21:01

Thalecress


1 Answers

You can use which and diff to help identify the where downward trend changes occur, and use cumsum to fill out the group membership.

# set up new column with all 0s
df$downward.trend.seq <- 0
# use diff to identify indices to change to 1
df$downward.trend.seq[which(c(NA, diff(df$measurement)) > 0)] <- 1
# use cumsum to fill in proper group membership
df$downward.trend.seq <- cumsum(df$downward.trend.seq)
like image 155
Jota Avatar answered Oct 26 '22 22:10

Jota