R: Populate column until the end and continue from the begining

Viewed 55

I have a dataframe with 2 columns

df <- structure(list(days = 1:10, days_fs = c(NA, NA, NA, NA, NA, 1, 
                                        NA, NA, NA, NA)), row.names = c(NA, -10L), class = "data.frame")

The number '1' in df$days_fs is just a marker, whose position will change as user input changes. What I need is to populate from the position of this '1' until the end of this vector, and then continue from the begining to have this:

df2 = structure(list(days = c(6L, 7L, 8L, 9L, 10L, 1L, 2L, 3L, 4L, 
5L), days_fs = 1:10), class = "data.frame", row.names = c(NA, 
-10L))

Well, I know I could make two vectors manually and use base R to fill this column with something like

df$days_fs[which(df$days_fs == 1):nrow(df)] <- seq(1,5)

etc. and then use dplyr::arrange.

There must be a more efficient (and readable) way to make this work within the tidyverse concept. Suggestions?

2 Answers

We could use

library(dplyr)
df %>%
   arrange(desc(cumsum(!is.na(days_fs)))) %>% 
   mutate(days_fs = row_number())

-output

#    days days_fs
#1     6       1
#2     7       2
#3     8       3
#4     9       4
#5    10       5
#6     1       6
#7     2       7
#8     3       8
#9     4       9
#10    5      10

Or the same logic in base R

transform(df[order(-cumsum(!is.na(df$days_fs))),], days_fs = seq_len(nrow(df)))

Another base R option

transform(
  df,
  days = unlist(split(seq_along(days_fs), rev(cumsum(!is.na(days_fs))))),
  days_fs = seq_along(days)
)

gives

   days days_fs
1     6       1
2     7       2
3     8       3
4     9       4
5    10       5
6     1       6
7     2       7
8     3       8
9     4       9
10    5      10
Related