Reputation: 61
I have a vector in R defined as c(2,3,4,6,5,3,1,3,5,6)
.
I want to subset the vector based on all increasing/decreasing trends in the vector.
The desired output should be 3 sub vectors (in this example)
1) (2,3,4,6)
2) (6,5,3,1)
3) (1,3,5,6)
Upvotes: 3
Views: 301
Reputation: 1305
Here is an answer that discriminates between up and down trends
dummy_vector = c(2,3,4,6,5,3,1,3,5,6)
# Loop to mark the trend
index = rep(1,length(dummy_vector)) # Pre allocate output vector
for (i in 2:length(dummy_vector)) {
if (dummy_vector[i] > dummy_vector[i-1]) {
index[i] = 1 # trend up
}
else if (dummy_vector[i] < dummy_vector[i-1]) {
index[i] = 2 # trend down
}
} # end loop
# Mark changes in trend
change_trend = rep(0,length(index)) # Pre allocate output vector
for (i in 2:length(index)) {
if (index[i] == 2 && index[i-1] == 1) {
change_trend[i-1] = 3
}
else if (index[i] == 1 && index[i-1] == 2) {
change_trend[i-1] = 3
}
} # end loop
# Grab index positions
up_trend_index_start = rep(0,length(index))
up_trend_index_end = rep(0,length(index))
dn_trend_index_start = rep(0,length(index))
dn_trend_index_end = rep(0,length(index))
for (i in 1:length(index)) {
if (index[i] == 1 && i == 1) {
up_trend_index_start[i] = i
}
if (index[i] == 2 && i == 1) {
dn_trend_index_start[i] = i
}
if (index[i] == 1 && change_trend[i] == 3 ) {
up_trend_index_end[i] = i
}
if (index[i] == 2 && change_trend[i] == 3 ) {
up_trend_index_start[i] = i
}
if (index[i] == 1 && change_trend[i] == 3 ) {
dn_trend_index_start[i] = i
}
if (index[i] == 2 && change_trend[i] == 3 ) {
dn_trend_index_end[i] = i
}
if (index[i] == 1 && i == length(index)) {
up_trend_index_end[i] = i
}
if (index[i] == 2 && i == length(index)) {
dn_trend_index_end[i] = i
}
}
# Reduce to remove all 0
up_trend_index_start = up_trend_index_start[up_trend_index_start != 0]
up_trend_index_end = up_trend_index_end[up_trend_index_end != 0]
dn_trend_index_start = dn_trend_index_start[dn_trend_index_start != 0]
dn_trend_index_end = dn_trend_index_end[dn_trend_index_end != 0]
# find maximum vector length
max_i = max(length(up_trend_index_start),length(up_trend_index_end),length(dn_trend_index_start),length(dn_trend_index_end))
# For loop to make subsets
up_trend = list()
dn_trend = list()
for (i in 1:max_i){
up_trend[[i]] = dummy_vector[up_trend_index_start[i]:up_trend_index_end[i]]
dn_trend[[i]] = dummy_vector[dn_trend_index_start[i]:dn_trend_index_end[i]]
if (i >= length(dn_trend_index_end) | i >= length(up_trend_index_end)) { # Break loop if uneven lengths
break
}
}
# Vector output
up_trend_one = up_trend[[1]]
dn_trend_one = dn_trend[[1]]
up_trend_two = up_trend[[2]]
For the output
> up_trend_one
[1] 2 3 4 6
> dn_trend_one
[1] 6 5 3 1
> up_trend_two
[1] 1 3 5 6
Upvotes: 1
Reputation: 32548
x = c(2, 3, 4, 6, 5, 3, 1, 3, 5, 6)
r = cumsum(rle(sign(diff(x)) >= 0)$lengths) + 1
lapply(seq_along(r), function(i){
x[max(1, r[i - 1]):r[i]]
})
#[[1]]
#[1] 2 3 4 6
#[[2]]
#[1] 6 5 3 1
#[[3]]
#[1] 1 3 5 6
Upvotes: 2