Increasing the next value in a column so all the values are increasing according to unique ID column in R

Viewed 58

I got some data such as this

structure(list(id = c(1, 1, 1, 2, 2, 2, 3, 3, 3), values = c(12, 
13, 13, 6, 5, 7, 8, 8, 8)), class = "data.frame", row.names = c(NA, 
-9L))

I want something like this

structure(list(id2 = c(1, 1, 1, 2, 2, 2, 3, 3, 3), values2 = c(12, 
13, 13.5, 6, 6.5, 7, 8, 8.5, 9)), class = "data.frame", row.names = c(NA, 
-9L))

I want to check if they values in the values column for each ID are in increasing.If two values are equal then increase the second value by 0.5. Similary if the next value is smaller increase it by o.5.

2 Answers

To My dear Friend @AnilGoyal

We can use accumulate function for this purpose:

  • I created a conditional statement comparing current value .y to the accumulated/ previous value .x
  • If the current value is greater than the previous value, the result will be the current value, otherwise we add 0.5 to the previous value
  • Bear in mind that in every accumulation .x represents the previous value while .y represents the new/ current value
library(purrr)

df %>%
  group_by(id) %>%
  mutate(values = accumulate(values, 
                             ~ if(.y > .x) {
                               .y
                             } else {
                               .x + 0.5
                             }))

# A tibble: 9 x 2
# Groups:   id [3]
     id values
  <dbl>  <dbl>
1     1   12  
2     1   13  
3     1   13.5
4     2    6  
5     2    6.5
6     2    7  
7     3    8  
8     3    8.5
9     3    9 

Using the rle() to create sequences of .5 steps.

do.call(rbind, by(dat, dat$id, \(x) {
  v <- x$value
  d <- diff(v)
  if (any(d < 0)) o <- seq(v[1], length.out=length(v), by=.5)
  else if (any(d == 0)) {
    r <- rle(v)
    o <- unlist(Map(\(y, z) seq(y, length.out=z, by=.5), r$values, r$lengths))
  }
  return(setNames(data.frame(x$id, o), names(x)))
}))
#     id values
# 1.1  1   12.0
# 1.2  1   13.0
# 1.3  1   13.5
# 2.1  2    6.0
# 2.2  2    6.5
# 2.3  2    7.0
# 3.1  3    8.0
# 3.2  3    8.5
# 3.3  3    9.0
Related