rdataframerename

Renaming columns in R 4.3 using native pipe


I have a sequence of operations that I use the R 4.3 pipe to execute:

df <- alfred::get_alfred_series(CHAUVET_PIGER_PROB)
unrevised_df <- df |>
                    within(Delta <- realtime_period - date) |>
                    na.omit() |>
                    subset(Delta == ave(Delta, date, FUN = min)) |>
                    subset(Delta <60) |>
                    within(date <- zoo::as.yearmon(format(date, format = '%Y-%m-%d'))) |>
                    subset(select = -c(Delta, realtime_period))


> head(unrevised_df)
           date UNRATE
146  1960-02-01    4.8
1065 1960-03-01    5.4
1984 1960-04-01    5.0
2903 1960-05-01    4.9
3822 1960-06-01    5.5
4741 1960-07-01    5.4

I would like to add one more line to my sequence to change the name of the first column from date to Date without having to invoke dplyr. I'm aware that I can simply add a separate line that reads colnames(unrevised_df[1]) <- "Date"

but I would like to make this a line in the pipe. How can I do this?

Your help is greatly appreciated.

Sincerely

Thomas Philips


Solution

  • Here are a few other approaches. The first uses an anonymous function and the others use the trick of boxing the input into a list.

    # 1
    unrevised_df |>
      (\(x) { names(x)[1] <- "Date"; x })()
    
    # 2
    unrevised_df |>
      list(x = _) |>
      with( { names(x)[1] <- "Date"; x } )
    
    # 3
    unrevised_df |>
      list(x = _) |>
      with( setNames(x, replace(names(x), 1, "Date")) )
    
    # 4
    unrevised_df |>
      list(x = _) |>
      with(cbind(Date = x[[1]], x[-1]))
    

    If you are willing to use magrittr (which is very stable and does not involve using dplyr, tidyr or any other tidyverse package) we can do this:

    # 5
    library(magrittr)
    unrevised_df %>%
      { names(.)[1] <- "Date"; . } 
    

    The Bizarro pipe is not really a pipe but just base R syntax that looks like one:

    # 6
    unrevised_df ->.;
      { names(.)[1] <- "Date"; . } 
    

    Another possibility is to define your own pipe. This pipe does not do automatic substitution but instead requires that dot (.) on the right hand side be used. It is only one additional line of code to define it keeping the code independent of any packages.

    "%.>%" <- function(left, right) eval(substitute(right), list(. = left))
    
    unrevised_df %.>%
      { names(.)[1] <- "Date"; . } 
    

    Note

    The input in reproducible form

    unrevised_df <- data.frame(
      date = c("1960-02-01", "1960-03-01", "1960-04-01", "1960-05-01", "1960-06-01", "1960-07-01"),
      UNRATE = c(4.8, 5.4, 5, 4.9, 5.5, 5.4),
      row.names = c("146", "1065", "1984", "2903", "3822", "4741")
    )