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
CodePudding user response:
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))
}))
CodePudding user response:
A possible alternative, although I like @GKi's( 1) function.
library(tidyverse)
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 |>
group_by(var) |>
mutate(fill = val) |>
fill(fill, .direction = "downup") |>
mutate(
index = which(!is.na(val)),
val2 = fill row_number() - index
)
#> # A tibble: 12 × 5
#> # Groups: var [3]
#> var val fill index val2
#> <chr> <dbl> <dbl> <int> <dbl>
#> 1 A 4 4 1 4
#> 2 A NA 4 1 5
#> 3 A NA 4 1 6
#> 4 B NA 9 3 7
#> 5 B NA 9 3 8
#> 6 B 9 9 3 9
#> 7 B NA 9 3 10
#> 8 C NA 20 5 16
#> 9 C NA 20 5 17
#> 10 C NA 20 5 18
#> 11 C NA 20 5 19
#> 12 C 20 20 5 20
Created on 2022-06-14 by the reprex package (v2.0.1)