'Get last entry of a range with identical numbers in R, vectorized

I’ve got this data:

tribble(
    ~ranges, ~last,
    0,     NA,
    1,     NA,
    1,     NA,
    1,     NA,
    1,     NA,
    2,     NA,
    2,     NA,
    2,     NA,
    3,     NA,
    3,     NA
)

and I want to fill the last column only at the row index at the last entry of the number by the ranges column. That means, it should look like this:

tribble(
    ~ranges, ~last,
    0,     0,
    1,     NA,
    1,     NA,
    1,     NA,
    1,     1,
    2,     NA,
    2,     NA,
    2,     2,
    3,     NA,
    3,     3
)

So far I came up with a row-wise approach:

for (r in seq.int(max(tmp$ranges))) {
  print(r)
  range <- which(tmp$ranges == r) |> max()
  tmp$last[range] <- r
}

The main issue is that it is terribly slow. I am looking for a vectorized approach to this issue. Any creative solution out there?

r


Solution 1:[1]

Using replace:

library(dplyr)
df %>% 
  group_by(ranges) %>% 
  mutate(last = replace(last, n(), ranges[n()]))

Using ifelse:

library(dplyr)
df %>% 
  group_by(ranges) %>% 
  mutate(last = ifelse(row_number() == n(), ranges, NA)) 

Using tail:

library(dplyr)
df %>% 
  group_by(ranges) %>% 
  mutate(last = c(last[-n()], tail(ranges, 1)))

output

   ranges  last
    <dbl> <dbl>
 1      0     0
 2      1    NA
 3      1    NA
 4      1    NA
 5      1     1
 6      2    NA
 7      2    NA
 8      2     2
 9      3    NA
10      3     3

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1