Примените разницу и среднее значение между группами в столбце R

#r #dplyr #tidyr

Вопрос:

У меня есть фрейм данных, такой :

 df = data.frame("subjectID" = c("S1","S2","S2","S1","S1","S2","S2","S1","S1","S2","S1","S2"), "treatment" = c("none","none","none","none","drug1","drug1","drug1","drug1","drug2","drug2","drug2","drug2"), "protein" = c("proteinA","proteinA","proteinB","proteinB","proteinA","proteinA","proteinB","proteinB","proteinA","proteinA","proteinB","proteinB"), "value"= c(5.3,4.3,4.5,2.3,6.5,5.4,1.2,3.2,2.3,4.5,6.5,3.4))

   subjectID treatment  protein value
1         S1      none proteinA   5.3
2         S2      none proteinA   4.3
3         S2      none proteinB   4.5
4         S1      none proteinB   2.3
5         S1     drug1 proteinA   6.5
6         S2     drug1 proteinA   5.4
7         S2     drug1 proteinB   1.2
8         S1     drug1 proteinB   3.2
9         S1     drug2 proteinA   2.3
10        S2     drug2 proteinA   4.5
11        S1     drug2 proteinB   6.5
12        S2     drug2 proteinB   3.4
 

Я должен выполнить следующие вычисления в этом фрейме данных:

  1. Найдите разницу в значении между лечением = «лекарство1» и лечением = «нет» для каждого белка для каждого субъекта.

Так что в основном для одного расчета это было бы :

 diff = df$value[df$subjectID == "S1" amp; df$treatment == "drug1" amp; df$protein == "proteinA"] - df$value[df$subjectID == "S1" amp; df$treatment == "none" amp; df$protein == "proteinA"] 
diff 
> 1.2 
 

В приведенном выше примере значения 6,5 — 5,3 дают разницу между образцом, обработанным лекарственным средством, и образцом, не прошедшим лечение, для белка. Я аналогично повторяю это для S2 и proteinA, S1/proteinB и S2/proteinB.

  1. Найдите среднюю разницу между испытуемыми.

Мои исходные данные содержат 5 разных субъектов, 10 различных методов лечения ( включая лечение == «нет») и 100 белков, и я не могу сделать это для каждой группы вручную. Мне нужно будет рассчитать среднюю разницу между каждым лекарственным лечением и отсутствием лечения ( 9 различных методов лечения против ни одного лечения ).

Желаемый результат может быть таким:

  resdf
   protein drug1_mean_diff drug2_mean_diff
1 proteinA             1.15            -1.4
2 proteinB             -1.2            1.55
 

В конечном итоге у меня должно быть 100 белков (строк) и 9 средних различий ( столбцов)

Надеюсь, это ясно.

Спасибо!

Комментарии:

1. Не могли бы вы, пожалуйста, обновить свой MRE, чтобы учесть новое ограничение (несколько методов лечения, которые все должны сравниваться с лечением-нет).?

2. обновлено по запросу

3. Вы уверены, что ваши ожидаемые выходные значения верны? Я не могу их воспроизвести…

Ответ №1:

 library(tidyverse)

df <- data.frame(
  "subjectID" = c("S1", "S2", "S2", "S1", "S1", "S2", "S2", "S1", "S1", "S2", "S1", "S2"),
  "treatment" = c("none", "none", "none", "none", "drug1", "drug1", "drug1", "drug1", "drug2", "drug2", "drug2", "drug2"),
  "protein" = c("proteinA", "proteinA", "proteinB", "proteinB", "proteinA", "proteinA", "proteinB", "proteinB", "proteinA", "proteinA", "proteinB", "proteinB"),
  "value" = c(5.3, 4.3, 4.5, 2.3, 6.5, 5.4, 1.2, 3.2, 2.3, 4.5, 6.5, 3.4)
)

# For every pair of protein and drug treatment
expand_grid(
  protein = df$protein %>% unique(),
  comparison = df$treatment %>% unique() %>% setdiff("none")
) %>%
  mutate(
    mean_diff = comparison %>% map2_dbl(protein, ~ {
      df %>%
        pivot_wider(names_from = treatment, values_from = value) %>%
        filter(protein == .y) %>%
        rename_at(.x, ~"drug") %>%
        mutate(diff = none - drug) %>%
        pull(diff) %>%
        mean()
    })
  ) %>%
  pivot_wider(names_from = comparison, values_from = mean_diff, names_prefix = "mean_diff_")
#> # A tibble: 2 x 3
#>   protein  mean_diff_drug1 mean_diff_drug2
#>   <chr>              <dbl>           <dbl>
#> 1 proteinA           -1.15            1.4 
#> 2 proteinB            1.2            -1.55
 

Создано 2021-10-05 пакетом reprex (v2.0.1)

Комментарии:

1. Как насчет лечения:лекарство2 — лечение:нет, лечение:лекарство3 — лечение:нет и т.д. ?

2. drug2 не был частью вашего примера в то время, когда я писал этот ответ… Подождите несколько минут

3. Это всегда было частью основного текста вопроса. Кроме того, я не являюсь автором вопроса 😉

4. Я пересмотрел свой ответ. Я также не могу воспроизвести пример результата, но разница такая же, как у @dario (он просто не принимал наркотики, я сделал это по — другому, поэтому у него другой знак).

5. Привет @danlooo, большое вам спасибо за ваш ответ. Это работает для MRE, но на самом деле у меня может быть или не быть префикса «наркотик» для всех наркотиков. Это то, что мне, возможно, придется добавить при использовании с вашим кодом.

Ответ №2:

Почему — то я не могу воспроизвести ожидаемый результат, как показано в вопросе. Однако я думаю, что этот код должен дать желаемый ответ. Но я мог ошибиться или что-то неправильно понять. Поэтому, пожалуйста, проверьте перед использованием кода:

   df = data.frame(subjectID = c("S1","S2","S2","S1","S1","S2","S2","S1","S1","S2","S1","S2"), 
                  treatment = c("none","none","none","none","drug1","drug1","drug1","drug1","drug2","drug2","drug2","drug2"),
                  protein = c("proteinA","proteinA","proteinB","proteinB","proteinA","proteinA","proteinB","proteinB","proteinA","proteinA","proteinB","proteinB"),
                  value = c(5.3,4.3,4.5,2.3,6.5,5.4,1.2,3.2,2.3,4.5,6.5,3.4))
  
  
  df %>% 
     filter(treatment != "none") %>% 
     left_join(df %>% filter(treatment == "none") %>% rename(control = value) %>% select(subjectID, protein, control)) %>% 
     mutate(diff = value - control) %>% 
     select(subjectID, protein, treatment, diff) %>% 
     pivot_wider(names_from = treatment, values_from = diff, names_prefix = "diff_") %>% 
     group_by(protein) %>% 
       summarise(across(starts_with("diff"), mean, rm.na=TRUE))
  
 

ВОЗВРАТ:

     protein  diff_drug1 diff_drug2
    <chr>         <dbl>      <dbl>
  1 proteinA       1.15      -1.4 
  2 proteinB      -1.20       1.55
 

Комментарии:

1. Привет, Дарио ! Да, я отредактировал ожидаемый результат . Извини, я виноват. Большое спасибо за помощь!