title: Wide to long format: how to average across specific columns (2 sets of columns)
body: <p>I have a dataset in wide format that I want to transform to long format. The columns in the wide format denote two levels of one long-format variable. I want to row-wise average across each set of columns in the wide format, and represent that value (the average), for each set of columns, in a summarized long format table.</p>
  
  <h2>Dummy Data</h2>
  
  <p>Let's say that I have data from a study that tested how veterinarians weighed animals. There are 10 veterinarians (those are the "subjects"), one in each row. As for the animals being weighed, there are either dogs or cats (6 of which kind). Each vet was measuring all the animals in either a clinic setting or house setting. I want to calculate, for each vet, a mean weight of (1) all dogs he/she measured, and (2) mean weight of all cats he/she measured.</p>
  
  <pre class="lang-r prettyprint-override"><code>library(tidyverse)
  
  set.seed(123)
  df &lt;- data.frame(replicate(12,sample(10:25,10,rep=TRUE)))
  id &lt;- 1:10
  clinic_vs_house &lt;- sample(c(0,1), 10, replace = TRUE)
  df &lt;- cbind(id, clinic_vs_house, df)
  names(df) &lt;- c("id",
                 "location",
                 "cat_a",
                 "cat_b",
                 "cat_c",
                 "cat_d",
                 "cat_e",
                 "cat_f",
                 "dog_a",
                 "dog_b",
                 "dog_c",
                 "dog_d",
                 "dog_e",
                 "dog_f")
  
  &gt; df
  ##    id location cat_a cat_b cat_c cat_d cat_e cat_f dog_a dog_b dog_c dog_d dog_e dog_f
  ## 1   1        0    24    13    18    18    24    21    14    15    23    15    18    25
  ## 2   2        1    24    23    21    23    25    14    17    14    15    11    13    23
  ## 3   3        0    12    15    18    12    19    16    21    24    20    10    15    21
  ## 4   4        0    23    18    18    13    22    14    24    18    17    11    18    24
  ## 5   5        0    12    19    22    23    16    20    22    24    15    13    25    18
  ## 6   6        1    19    20    12    10    18    25    11    19    15    22    23    23
  ## 7   7        1    11    25    17    20    18    15    10    21    16    14    18    23
  ## 8   8        0    15    14    19    16    19    18    18    24    24    15    16    25
  ## 9   9        0    20    12    16    14    16    11    20    25    25    24    12    12
  ## 10 10        0    14    20    19    21    20    22    18    13    10    12    17    23
  </code></pre>
  
  <h2>My current clunky solution</h2>
  
  <p>I created two separate dataframes, each one for a different set of animals, where I calculate the mean for the relevant columns. Then I merged the tables.</p>
  
  <pre class="lang-r prettyprint-override"><code>cat_means &lt;- 
    df %&gt;%
    mutate(mean_wt = rowMeans(select(., matches("cat")))) %&gt;%
    select(id, location, mean_wt) %&gt;%
    mutate(animal = "cat")
  
  
  dog_means &lt;- 
    df %&gt;%
    mutate(mean_wt = rowMeans(select(., matches("dog")))) %&gt;%
    select(id, location, mean_wt) %&gt;%
    mutate(animal = "dog")
  
  
  means_table &lt;-
    bind_rows(cat_means, dog_means) %&gt;%
    select(id, location, animal, mean_wt) %&gt;%
    arrange(id)
  
  &gt; means_table
  ##    id location animal  mean_wt
  ## 1   1        0    cat 16.85714
  ## 2   1        0    dog 18.33333
  ## 3   2        1    cat 18.71429
  ## 4   2        1    dog 15.50000
  ## 5   3        0    cat 13.14286
  ## 6   3        0    dog 18.50000
  ## 7   4        0    cat 15.42857
  ## 8   4        0    dog 18.66667
  ## 9   5        0    cat 16.00000
  ## 10  5        0    dog 19.50000
  ## 11  6        1    cat 15.00000
  ## 12  6        1    dog 18.83333
  ## 13  7        1    cat 15.28571
  ## 14  7        1    dog 17.00000
  ## 15  8        0    cat 14.42857
  ## 16  8        0    dog 20.33333
  ## 17  9        0    cat 12.71429
  ## 18  9        0    dog 19.66667
  ## 19 10        0    cat 16.57143
  ## 20 10        0    dog 15.50000
  </code></pre>
  
  <p>So yes, I was able to get the result I wanted, but I'm unhappy with this solution because it's repetitive code, and would be a pain if I have more than just 2 sets of columns to transform. Is there a more concise way to get the same result? I know that I can always write a function to be run x times, but I was wondering if there's a more elegant solution I'm unaware of, particularly using <code>tidyverse</code>.</p>