'use a wildcard in mutate() to modify several variables with corresponding names
I have a database with multiple columns of numerical data which i need to subtract from each other.
they are named t1 and c1 correspondingly, up to t7 and c7. Is there a succinct way using the tidy verse that I can create a new variable (delta) for each of these?
e.g.
df <- df %>%
mutate(d* = t* - c*)
rather than having to write
df <- df %>%
mutate(d1 = t1 - c1) %>%
mutate(d2 = t2 - c2) %>%
etc.
Solution 1:[1]
Suppose your data frame looks like this
set.seed(1)
df <- as.data.frame(matrix(rnorm(70), ncol = 14))
df <- setNames(df, c(paste0("c", 1:7), paste0("t", 1:7)))
df
#> c1 c2 c3 c4 c5 c6
#> 1 -0.6264538 -0.8204684 1.5117812 -0.04493361 0.91897737 -0.05612874
#> 2 0.1836433 0.4874291 0.3898432 -0.01619026 0.78213630 -0.15579551
#> 3 -0.8356286 0.7383247 -0.6212406 0.94383621 0.07456498 -1.47075238
#> 4 1.5952808 0.5757814 -2.2146999 0.82122120 -1.98935170 -0.47815006
#> 5 0.3295078 -0.3053884 1.1249309 0.59390132 0.61982575 0.41794156
#> c7 t1 t2 t3 t4 t5
#> 1 1.35867955 -0.4149946 -0.1645236 -0.7074952 0.3981059 1.9803999
#> 2 -0.10278773 -0.3942900 -0.2533617 0.3645820 -0.6120264 -0.3672215
#> 3 0.38767161 -0.0593134 0.6969634 0.7685329 0.3411197 -1.0441346
#> 4 -0.05380504 1.1000254 0.5566632 -0.1123462 -1.1293631 0.5697196
#> 5 -1.37705956 0.7631757 -0.6887557 0.8811077 1.4330237 -0.1350546
#> t6 t7
#> 1 2.40161776 0.1887923
#> 2 -0.03924000 -1.8049586
#> 3 0.68973936 1.4655549
#> 4 0.02800216 0.1532533
#> 5 -0.74327321 2.1726117
Then you can do this in base R with the following one-liner:
setNames(df[paste0("c", 1:7)] - df[paste0("t", 1:7)], paste0("delta", 1:7))
#> delta1 delta2 delta3 delta4 delta5 delta6
#> 1 -0.2114592 -0.65594479 2.21927633 -0.4430395 -1.0614225 -2.4577465
#> 2 0.5779333 0.74079073 0.02526127 0.5958361 1.1493578 -0.1165555
#> 3 -0.7763152 0.04136133 -1.38977351 0.6027165 1.1186996 -2.1604917
#> 4 0.4952554 0.01911815 -2.10235368 1.9505843 -2.5590713 -0.5061522
#> 5 -0.4336680 0.38336731 0.24382319 -0.8391224 0.7548804 1.1612148
#> delta7
#> 1 1.1698873
#> 2 1.7021709
#> 3 -1.0778833
#> 4 -0.2070584
#> 5 -3.5496712
Or, if you have to do it in the tidyverse, the equivalent might be something like:
df %>% mutate(delta = across(starts_with("c")) - across(starts_with("t")))
#> c1 c2 c3 c4 c5 c6
#> 1 -0.6264538 -0.8204684 1.5117812 -0.04493361 0.91897737 -0.05612874
#> 2 0.1836433 0.4874291 0.3898432 -0.01619026 0.78213630 -0.15579551
#> 3 -0.8356286 0.7383247 -0.6212406 0.94383621 0.07456498 -1.47075238
#> 4 1.5952808 0.5757814 -2.2146999 0.82122120 -1.98935170 -0.47815006
#> 5 0.3295078 -0.3053884 1.1249309 0.59390132 0.61982575 0.41794156
#> c7 t1 t2 t3 t4 t5
#> 1 1.35867955 -0.4149946 -0.1645236 -0.7074952 0.3981059 1.9803999
#> 2 -0.10278773 -0.3942900 -0.2533617 0.3645820 -0.6120264 -0.3672215
#> 3 0.38767161 -0.0593134 0.6969634 0.7685329 0.3411197 -1.0441346
#> 4 -0.05380504 1.1000254 0.5566632 -0.1123462 -1.1293631 0.5697196
#> 5 -1.37705956 0.7631757 -0.6887557 0.8811077 1.4330237 -0.1350546
#> t6 t7 delta.c1 delta.c2 delta.c3 delta.c4
#> 1 2.40161776 0.1887923 -0.2114592 -0.65594479 2.21927633 -0.4430395
#> 2 -0.03924000 -1.8049586 0.5779333 0.74079073 0.02526127 0.5958361
#> 3 0.68973936 1.4655549 -0.7763152 0.04136133 -1.38977351 0.6027165
#> 4 0.02800216 0.1532533 0.4952554 0.01911815 -2.10235368 1.9505843
#> 5 -0.74327321 2.1726117 -0.4336680 0.38336731 0.24382319 -0.8391224
#> delta.c5 delta.c6 delta.c7
#> 1 -1.0614225 -2.4577465 1.1698873
#> 2 1.1493578 -0.1165555 1.7021709
#> 3 1.1186996 -2.1604917 -1.0778833
#> 4 -2.5590713 -0.5061522 -0.2070584
#> 5 0.7548804 1.1612148 -3.5496712
Created on 2022-01-28 by the reprex package (v2.0.1)
Solution 2:[2]
Here's an alternative way:
library(tidyverse)
set.seed(111)
# some data
df <-
map_dfc(c("t", "c"), ~ {
nms <- str_c(.x, 1:3)
map_dfc(nms, ~ tibble("{.x}" := rnorm(10)))
})
d_df <-
as.character(1:3) %>%
map_dfc(~ select(df, ends_with(.x)) %>%
transmute('d{.x}' := reduce(., `-`)))
bind_cols(df, d_df)
#> # A tibble: 10 × 9
#> t1 t2 t3 c1 c2 c3 d1 d2 d3
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 0.235 -0.174 0.362 -3.11 -1.18 0.192 3.35 1.00 0.170
#> 2 -0.331 -0.407 0.347 -0.941 -1.12 1.55 0.611 0.715 -1.21
#> 3 -0.312 1.85 0.190 1.40 -1.36 0.914 -1.71 3.21 -0.725
#> 4 -2.30 0.394 -0.160 -1.62 0.481 0.359 -0.682 -0.0871 -0.518
#> 5 -0.171 0.798 0.327 -2.27 0.742 0.175 2.10 0.0556 0.151
#> 6 0.140 -1.57 0.598 1.16 0.0278 -0.847 -1.02 -1.59 1.45
#> 7 -1.50 -0.0859 -1.84 -0.116 0.331 0.978 -1.38 -0.417 -2.82
#> 8 -1.01 -0.359 2.72 0.334 0.644 1.81 -1.34 -1.00 0.912
#> 9 -0.948 -1.19 0.191 -0.621 2.49 0.123 -0.328 -3.68 0.0683
#> 10 -0.494 0.364 -1.30 -1.31 1.96 -0.130 0.816 -1.60 -1.17
Created on 2022-01-28 by the reprex package (v2.0.1)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | jpdugo17 |
