Search code examples
rmissing-data

Expand value to sequence


I have such a data frame consisting of different groups of differing lengths. In each group, all but one value are NA but this non-NA value can be at any position. How can I expand the val column to create a sequence of ascending values per group?

dat <- data.frame(var = c(rep("A", 3), rep("B", 4), rep("C",5)),
                  val = c(4, NA, NA, NA, NA, 9, NA, NA, NA, NA, NA, 20))
> dat
   var val
1    A   4
2    A  NA
3    A  NA
4    B  NA
5    B  NA
6    B   9
7    B  NA
8    C  NA
9    C  NA
10   C  NA
11   C  NA
12   C  20

Desired output:

> dat 
   var val
1    A   4
2    A   5
3    A   6
4    B   7
5    B   8
6    B   9
7    B  10
8    C  16
9    C  17
10   C  18
11   C  19
12   C  20

Solution

  • Make a seq_along, subtract the index where the non NA is and add the non NA value.

    cbind(dat, fill = ave(dat$val, dat$var, FUN = function(x) {
      i <- which.max(!is.na(x))
      seq_along(x) - i + x[i]
    }))
    #   var val fill
    #1    A   4    4
    #2    A  NA    5
    #3    A  NA    6
    #4    B  NA    7
    #5    B  NA    8
    #6    B   9    9
    #7    B  NA   10
    #8    C  NA   16
    #9    C  NA   17
    #10   C  NA   18
    #11   C  NA   19
    #12   C  20   20
    

    or

    cbind(dat, fill = ave(dat$val, dat$var, FUN = function(x) {
      i <- which.max(!is.na(x))
      seq(x[i] - i + 1, length.out = length(x))
    }))