Home > Mobile >  What is the most efficient way to subtract several different columns using dplyr
What is the most efficient way to subtract several different columns using dplyr

Time:12-28

I have a dataset like this:

data.frame(x = c(1:5), y = c(0:4), z = c(2:6))

  x y z
1 1 0 2
2 2 1 3
3 3 2 4
4 4 3 5
5 5 4 6

I would like to get a dataset like this:

  x y z y-x z-y
1 1 0 2  -1   2
2 2 1 3  -1   2
3 3 2 4  -1   2
4 4 3 5  -1   2
5 5 4 6  -1   2

when I use:

a <- a %>% mutate(across((x:z), ~. - lag(.)))

I get:

   x  y  z
1 NA NA NA
2  1  1  1
3  1  1  1
4  1  1  1
5  1  1  1

That is, the mutate is subtracting in the same column and I needed to subtract in different columns. How can I resolve this?

CodePudding user response:

I wouldn't use dplyr for this. I would use base R directly:

diff_cols = your_data[-1] - your_data[-ncol(your_data)]
names(diff_cols) = paste0(
  names(your_data)[-1],
  "-",
  names(your_data)[-ncol(your_data)]
)
cbind(your_data, diff_cols)
#   x y z y-x z-y
# 1 1 0 2  -1   2
# 2 2 1 3  -1   2
# 3 3 2 4  -1   2
# 4 4 3 5  -1   2
# 5 5 4 6  -1   2

CodePudding user response:

Using dplyr you could do this:

library(dplyr, warn.conflicts = FALSE)


df1 <- data.frame(x = c(1:5), y = c(0:4), z = c(2:6))

df1 |> 
  mutate(`y-x` = y - x,
         `z-y` = z - y)
#> # A tibble: 5 × 5
#> # Rowwise: 
#>       x     y     z `y-x` `z-y`
#>   <int> <int> <int> <int> <int>
#> 1     1     0     2    -1     2
#> 2     2     1     3    -1     2
#> 3     3     2     4    -1     2
#> 4     4     3     5    -1     2
#> 5     5     4     6    -1     2

Created on 2022-12-27 with reprex v2.0.2

CodePudding user response:

You could use something like

library(dplyr)

df %>% 
  mutate(across(x:y, 
                ~. - df[[names(df)[which(names(df) == cur_column())   1]]],
                .names = "{.col}-{names(df)[which(names(df) == .col)   1]}")
         )

This returns

  x y z x-y y-z
1 1 0 2   1  -2
2 2 1 3   1  -2
3 3 2 4   1  -2
4 4 3 5   1  -2
5 5 4 6   1  -2
Warning message:
Problem while computing `..1 = across(...)`.
ℹ longer object length is not a multiple of shorter object length 

but casts a warning which I can't remove.

  • Related