Home > database >  How to replace mutate_ with mutate when using a series to replace swap columns?
How to replace mutate_ with mutate when using a series to replace swap columns?

Time:03-17

I am looking to replace mutate_ with mutate since there are deprecation warnings now and am unsure how to use some of the answers I have sought out on Stack Overflow. This answer has the deprecated quosure issue and not sure how this one can be applied.

library(tibble)
library(dplyr)
library(magrittr)
library(rlang)

# two data frames/tibbles
df1 <- 
  data.frame(
    w = c(0,9,8),
    x = c(1,2,3),
    y = c(4,5,6)
  ) %>% tibble()

df2 <- 
  data.frame(
    x = c(9,9,9),
    y = c(1,1,1),
    z = c(6,6,6)
  ) %>% tibble()

# the original function
swapThem <- function(to, from) {

  cols <- colnames(from)
  
  if (length(cols) != 0) {
    
    # Loop through `from` columns and if there's a match in `to`, copy and paste
    #   it into `to`
    for (i in seq_along(cols)) {
      col <- cols[i]
      if (col %in% colnames(to)) {
        print(col)
        
        dots <-
          stats::setNames(list(lazyeval::interp(
            ~ magrittr::use_series(from, x), x = as.name(col)
          )), col)
        
        to <- to %>%
          #dplyr::mutate(.dots = dots)
          dplyr::mutate_(.dots = dots)
      } else {
        next
      }
    }
  }
  return(to)
}

CodePudding user response:

Here is a simpler base R alternative -

swapThem <- function(to, from) {
  cols <- intersect(colnames(to), colnames(from)) 
  if(length(cols))  to[cols] <- from[cols]
  to
}

swapThem(df1, df2)

# A tibble: 3 × 3
#      w     x     y
#  <dbl> <dbl> <dbl>
#1     0     9     1
#2     9     9     1
#3     8     9     1

The output is similar when I run your code with swapThem(df1, df2) I get

#[1] "x"
#[1] "y"
# A tibble: 3 × 3
#      w     x     y
#  <dbl> <dbl> <dbl>
#1     0     9     1
#2     9     9     1
#3     8     9     1

CodePudding user response:

There are easier ways to do this (see Ronak Shah's base R approach, for example), however since you specifically asked about how to switch from mutate_ to mutate, you can adjust your original code in this way:

swapThem <- function(to, from) {
  
  cols <- colnames(from)
  
  if (length(cols) != 0) {
    
    # Loop through `from` columns and if there's a match in `to`, copy and paste
    #   it into `to`
    for (i in seq_along(cols)) {
      col <- cols[i]
      if (col %in% colnames(to)) {
        to <- to %>% dplyr::mutate(!!sym(col) := from[[col]])
      } else {
        next
      }
    }
  }
  return(to)
}

Note that you can also use {{}}, like this:

to <- to %>% dplyr::mutate({{col}} := from[[col]])

Here is another tidy approach, that uses bind_cols. The relocate is to ensure that the order of columns in to is preserved

swapThem <- function(to,from) {
  bind_cols(
    to %>% select(all_of(setdiff(colnames(to), colnames(from)))),
    from %>% select(all_of(intersect(colnames(to), colnames(from))))
  ) %>% 
    relocate(colnames(to))
}
  • Related