rloopsdplyr

Loop/apply in R to create new columns that calculate the difference between pairs of columns


I have a data frame that has multiple sets of pre/post measurements, and I'd like to create a new column for each that calculate the difference (change) in each variable.

Example data


df <- structure(list(Leptin_OVX = c(101537.030773452, 34184.1969018313, 
54567.1867690491, 29558.5420636246, 40929.680418857), Leptin_SAC = c(19785.945743781, 
124224.32770312, 89539.7367479193, 29335.4677793977, 49085.7085270132
), MIP1A_OVX = c(198.955714001384, 9.39084362457698, 6.31036668689314, 
31.4248133610863, 61.7242016227428), MIP1A_SAC = c(152.595958885867, 
0, 6.31036668689314, 12.0518867341972, 56.3458462409656), IL4_OVX = c(84.3973038052031, 
0, 0, 84.3973038052031, 0), IL4_SAC = c(0, 0, 0, 0, 0), IL1B_OVX = c(20.5433459761151, 
0, 0, 0, 26.9522602664794), IL1B_SAC = c(0, 18.9503177384518, 
14.986896887192, 0, 0)), row.names = c(NA, -5L), class = c("tbl_df", 
"tbl", "data.frame"))

I can do this manually as follows:


df <- df %>%
  mutate(chg_Leptin = Leptin_SAC - Leptin_OVX) %>%
  mutate(chg_MIP1A = MIP1A_SAC - MIP1A_OVX) %>%
  mutate(chg_IL4 = IL4_SAC - IL4_OVX) %>%
  mutate(chg_IL1B = IL1B_SAC - IL1B_OVX)

I'm trying to figure out a way to do this in a loop across all the remaining columns were I want to subtract the values from the "_SAC" column from the associated "_OVX" column

Thanks for the help!


Solution

  • We can use across, with some name-changing:

    df %>%
      mutate(
        across(ends_with("_SAC"),
               ~ .x - get(sub("_SAC$", "_OVX", cur_column())),
               .names = "chg_{sub('_SAC$','',.col)}")
      )
    # # A tibble: 5 × 12
    #   Leptin_OVX Leptin_SAC MIP1A_OVX MIP1A_SAC IL4_OVX IL4_SAC IL1B_OVX IL1B_SAC chg_Leptin chg_MIP1A chg_IL4 chg_IL1B
    #        <dbl>      <dbl>     <dbl>     <dbl>   <dbl>   <dbl>    <dbl>    <dbl>      <dbl>     <dbl>   <dbl>    <dbl>
    # 1    101537.     19786.    199.      153.      84.4       0     20.5      0      -81751.    -46.4    -84.4    -20.5
    # 2     34184.    124224.      9.39      0        0         0      0       19.0     90040.     -9.39     0       19.0
    # 3     54567.     89540.      6.31      6.31     0         0      0       15.0     34973.      0        0       15.0
    # 4     29559.     29335.     31.4      12.1     84.4       0      0        0        -223.    -19.4    -84.4      0  
    # 5     40930.     49086.     61.7      56.3      0         0     27.0      0        8156.     -5.38     0      -27.0