2016-07-11 1 views
1

У меня есть блок данных, содержащий несколько наблюдений из контрольной и экспериментальной когорт с репликациями для каждого объекта.Как связать строки в кадре данных со многими столбцами, используя dplyr в R?

Вот пример моего dataframe:

subject cohort replicate val1 val2 
    A  control  1  10  0.1 
    A  control  2  15  0.3 
    A  experim  1  40  0.7 
    A  experim  2  45  0.9 
    B  control  1  5  0.3  
    B  experim  1  30  0.0 
    C  control  1  50  0.5 
    C  experim  1  NA  1.0 

Я хотел бы пару каждого наблюдения управления с его соответствующим экспериментальными одному для каждого значения для вычисления отношения между парами. Нужный результат будет выглядеть примерно так:

subject replicate ratio_val1 ratio_val2 
    A   1   4    7 
    A   2   3    3 
    B   1   6    0 
    C   1   NA    2 

В идеале я хотел бы, чтобы это реализовать с dplyr и труб.

ответ

1

Мы можем использовать data.table путем изменения формы набора данных в формате «широкой».

library(data.table) 
dcast(setDT(df1), subject+replicate~cohort, value.var = c("val1", "val2"))[, 
      paste0("ratio_", names(df1)[4:5]) := Map(`/`, .SD[, 
     grep("experim", names(.SD)), with = FALSE], 
     .SD [, grep("control", names(.SD)), with = FALSE])][, (3:6) := NULL][] 
# subject replicate ratio_val1 ratio_val2 
# 1:  A   1   4   7 
# 2:  A   2   3   3 
# 3:  B   1   6   0 
# 4:  C   1   NA   2 

Или после того, как группировка с «предметом», «повторностью», мы перебираем столбцы «VAL» и разделить соответствующие элементы «Вала» для «experim» с тем из «контроля»

setDT(df1)[, lapply(.SD[, grep("val", names(.SD)), with = FALSE], 
    function(x) x[cohort =="experim"]/x[cohort =="control"]) , 
       by = .(subject, replicate)] 

Или мы можем использовать gather/spread из tidyr

library(dplyr) 
library(tidyr) 
df1 %>% 
    gather(Var, Val, val1:val2) %>% 
    spread(cohort, Val) %>% 
    group_by(subject, replicate, Var) %>% 
    summarise(ratio = experim/control) %>% spread(Var, ratio) 
# subject replicate val1 val2 
#  <chr>  <int> <dbl> <dbl> 
# 1  A   1  4  7 
# 2  A   2  3  3 
# 3  B   1  6  0 
# 4  C   1 NA  2 
+0

Точно, что я искал, @akrun! Я вижу, что group_by дает только одну строку в каждой группе. Таким образом, альтернативой будет «df1%>% gather (Var, Val, val1: val2)%>% спрэд (когорт, вал)%>% мутировать (соотношение = эксперимент/контроль)%>% select (-control, -experim)%>% спрэд (Var, ratio) ' – Irakli

+1

потрясающий и проработан! – Irakli

1

Вы можете использовать функцию summarize_at из dplyr суммировать столбцы val1 и val2 после группировки данных по subject и replicate. Используйте [cohort == ...] подобрать значения в эксперименте и контрольной группы, соответственно, для разделения:

library(dplyr) 
df %>% group_by(subject, replicate) %>% 
     summarize_at(vars(contains('val')), 
        funs("ratio" = .[cohort == "experim"]/.[cohort == "control"])) 

# Source: local data frame [4 x 4] 
# Groups: subject [?] 
# 
# subject replicate val1_ratio val2_ratio 
# <fctr>  <int>  <dbl>  <dbl> 
# 1  A   1   4   7 
# 2  A   2   3   3 
# 3  B   1   6   0 
# 4  C   1   NA   2 
+0

Спасибо @Psidom! Когда есть только один столбец значений, [ответ такой простой] (http://stackoverflow.com/questions/38295777/how-to-pair-rows-in-a-data-frame-in-r-with- dplyr). Существует ли простое решение для случая столбцов с несколькими значениями? – Irakli

+0

В dplyr 0.4.3, я не вижу totalize_at. Вы имеете в виду sumize_each? – Irakli

+0

Я использую 'dplyr' 0.5.0. И 'summaryize_at' - это новый API для' dplyr', поэтому, если вы обновите свой пакет 'dplyr', вы увидите его, а также' summaryize_each' будет устаревать в будущем, в то время как вы все еще можете использовать его сейчас лучше привыкнуть к этим новым API. – Psidom

Смежные вопросы