2015-02-16 3 views
21

У меня вопрос о функции Reduce в R. Я читаю его документацию, но я все еще немного смущен. Итак, у меня есть 5 векторов с именем генов. Например:Поймите функцию `Reduce`

v1 <- c("geneA","geneB",""...) 
v2 <- c("geneA","geneC",""...) 
v3 <- c("geneD","geneE",""...) 
v4 <- c("geneA","geneE",""...) 
v5 <- c("geneB","geneC",""...) 

И я хотел бы узнать, какие гены присутствуют, по крайней мере, в двух векторах. Некоторые люди предполагают:

Reduce(intersect,list(a,b,c,d,e)) 

Я был бы весьма признателен, если кто-то может пожалуйста, объясните мне, как работает это утверждение, потому что я видел Снизить использовать в других сценариях. Спасибо!

+3

Ваш вопрос действительно " Как я могу найти, какие гены/элементы присутствуют, по крайней мере, в двух векторах? " Если это так, 'Reduce()' is * not * будет полезным, хотя это позволит легко ответить на вопрос «какие гены присутствуют в ** все ** векторов?» –

ответ

23

Reduce принимает двоичную функцию и список элементов данных и последовательно применяет функцию к элементам списка рекурсивным образом. Например:

Reduce(intersect,list(a,b,c)) 

такого же, как

intersect((intersect(a,b),c) 

Однако, я не думаю, что конструкция поможет вам здесь, как он будет возвращать только те элементы, которые являются общими для всех векторов.

Чтобы подсчитать количество векторов, которое появляется ген в вас может сделать следующее:

vlist <- list(v1,v2,v3,v4,v5) 
addmargins(table(gene=unlist(vlist), vec=rep(paste0("v",1:5),times=sapply(vlist,length))),2,list(Count=function(x) sum(x[x>0]))) 
     vec 
gene v1 v2 v3 v4 v5 Count 
    geneA 1 1 0 1 0  3 
    geneB 1 0 0 0 1  2 
    geneC 0 1 0 0 1  2 
    geneD 0 0 1 0 0  1 
    geneE 0 0 1 1 0  2 
+0

Большое спасибо за ваш ввод. Я никогда раньше не использовал функции table и addmargins. Если вы не возражаете, я хотел бы спросить вас о них. – Johnathan

+0

таблица: поэтому ген - это объект, который может использоваться как фактор (т. Е. Категориальные данные), а vec - это названия размеров (т. Е. «V1», «v2»), правильно? Я смущен тем, что означает время.Он возвращает векторы длины. Что касается addmargins, это функция, которая расширяет таблицу для добавления предельных итогов (т. Е. Общее количество случаев по категориям интересов), правильно? «2» означает добавление столбца, который будет содержать маргинальные суммы строк, не так ли? Наконец, последний аргумент - это список, содержащий функцию. Спасибо за ваше время и помощь! – Johnathan

+1

@ Джонатан. Да, вы правы. 'times' - это аргумент' rep', который определяет, сколько раз каждый элемент повторяется, - чтобы обеспечить соответствие генов правильной переменной. – James

23

Хороший способ видеть, что Reduce() делает это, чтобы запустить его с аргументом accumulate=TRUE. Когда accumulate=TRUE, он вернет вектор или список, в котором каждый элемент показывает свое состояние после обработки первых n элементов списка в x. Вот несколько примеров:

Reduce(`*`, x=list(5,4,3,2), accumulate=TRUE) 
# [1] 5 20 60 120 

i2 <- seq(0,100,by=2) 
i3 <- seq(0,100,by=3) 
i5 <- seq(0,100,by=5) 
Reduce(intersect, x=list(i2,i3,i5), accumulate=TRUE) 
# [[1]] 
# [1] 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 
# [20] 38 40 42 44 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 
# [39] 76 78 80 82 84 86 88 90 92 94 96 98 100 
# 
# [[2]] 
# [1] 0 6 12 18 24 30 36 42 48 54 60 66 72 78 84 90 96 
# 
# [[3]] 
# [1] 0 30 60 90 
+0

Может ли он использоваться с большим количеством сравнений, очевидно, я попробовал это, и я получил первое число в последовательности, за которым следуют либо 11111, либо 00000. Мои ожидаемые значения для чего-то вроде Reduce ('<', c (3,4,7, 2,6,8,9), accumulate = T) было бы 3 3 2 2 2 2. Достижимо ли это с помощью Сокращения? Немного объясняя, я предположил, что Сокращение принимает элементы вектора 2 за раз, начиная с левой. Поскольку моя функция «меньше», она сравнивает первые 2 с возвратом меньшего числа, а затем сравнивает это с 3-м возвратом меньшего размера ... – user3507767

+0

просто для уточнения, я знаю, что могу получить желаемые результаты с помощью cummin(), просто пытаясь понять Reduce() здесь. – user3507767

6

Предполагая, что входные значения, приведенные в конце этого ответа, выражение

Reduce(intersect,list(a,b,c,d,e)) 
## character(0) 

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

intersect(intersect(intersect(intersect(a, b), c), d), e) 
## character(0) 

Если мы хотим, чтобы гены, которые, по крайней мере, двух векторов:

L <- list(a, b, c, d, e) 
u <- unlist(lapply(L, unique)) # or: Reduce(c, lapply(L, unique)) 

tab <- table(u) 
names(tab[tab > 1]) 
## [1] "geneA" "geneB" "geneC" "geneE" 

или

sort(unique(u[duplicated(u)])) 
## [1] "geneA" "geneB" "geneC" "geneE" 

Примечание: Мы использовали:

a <- c("geneA","geneB") 
b <- c("geneA","geneC") 
c <- c("geneD","geneE") 
d <- c("geneA","geneE") 
e <- c("geneB","geneC") 
Смежные вопросы