Search code examples
rtidyverse

How to shift all values in all columns of a data.frame() by n columns


I have a data.frame that looks like this.

df <-
  tibble::tribble(
    ~name,   ~age,          ~birthday,     ~address,   ~favorite_fruit,
    'josh',  '26',           '1998-04-14', '1 main st',  'banana',
    'jason', '2000-09-01',   '2 front st', 'apple',     NA,
    'nate',  '1992-dec-25',  '3 oak st',   'blueberry', NA
  )

df
#> # A tibble: 3 x 5
#>   name  age         birthday   address   favorite_fruit
#>   <chr> <chr>       <chr>      <chr>     <chr>         
#> 1 josh  26          1998-04-14 1 main st banana        
#> 2 jason 2000-09-01  2 front st apple     <NA>          
#> 3 nate  1992-dec-25 3 oak st   blueberry <NA>

As you might notice, age data was not collected for all people (ignoring that I could calculate it from birthday). Therefore, all values in some rows after the name column are incorrectly shifted to the left by one column. My ideal output would be NAs in the age column and the correct values in all other columns. How can I achieve this? If possible, a tidyverse solution is preferred.


Solution

  • You could use shift_row_values() from the hacksaw package:

    library(hacksaw)
    library(dplyr)
    
    bind_cols(select(df, name), 
              select(df, -name) |>
                shift_row_values(.dir = "right", at = is.na(df$favorite_fruit)))
    #   name  age   birthday    address    favorite_fruit
    #   <chr> <chr> <chr>       <chr>      <chr>         
    # 1 josh  26    1998-04-14  1 main st  banana        
    # 2 jason NA    2000-09-01  2 front st apple         
    # 3 nate  NA    1992-dec-25 3 oak st   blueberry