2015-12-07 3 views
3

У меня есть результаты исследования, хранящиеся в списках.Добавить несколько списков

Всего у меня 1000 списков, все из которых имеют одинаковое измерение.

Каждый список содержит 39 элементов, которые являются матрицами разных размеров.

Я хотел бы подвести этот список, а затем разделить их на 1000.

Я не мог придумать, как сделать это.

Пример:

a<-matrix(0,nrow=5,ncol=6) 
b<-matrix(0,nrow=2,ncol=10) 

list1 <- list(a,b) 

a<-matrix(0,nrow=5,ncol=6) 
b<-matrix(0,nrow=2,ncol=10) 

list2 <- list(a,b) 

a<-matrix(0,nrow=5,ncol=6) 
b<-matrix(0,nrow=2,ncol=10) 

list3 <- list(a,b) 

Я хочу добавить песни1 + песни2 + песни3 ... list1000

, а затем разделить каждый элемент в окончательном списке 1000.

+0

Положение каждой матрицы одинакова в каждом списке, так что я хочу, чтобы добавить каждую матрицу в одной и той же матрицы – user3742038

+0

ли списки с вашими реальными результатами также отдельные переменные, такие как '' list1', list2', .. .? Или они хранятся в каком-то другом списке? – Julius

+0

хранятся в отдельных файлах Rdata. – user3742038

ответ

3

Вы можете использовать комбинацию из Map и Reduce и используйте mget, чтобы собрать все ваши списки в один список.

a<-matrix(1,nrow=5,ncol=6) 
b<-matrix(10,nrow=2,ncol=10) 

list1 <- list(a,b) 
list2 <- list(a,b) 
list3 <- list(a,b) 

l <- mget(ls(pattern = '^list\\d+$')) 
(fl <- Reduce(function(x, y) Map(`+`, x, y), l)) 

# [[1]] 
#  [,1] [,2] [,3] [,4] [,5] [,6] 
# [1,] 3 3 3 3 3 3 
# [2,] 3 3 3 3 3 3 
# [3,] 3 3 3 3 3 3 
# [4,] 3 3 3 3 3 3 
# [5,] 3 3 3 3 3 3 
# 
# [[2]] 
#  [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] 
# [1,] 30 30 30 30 30 30 30 30 30 30 
# [2,] 30 30 30 30 30 30 30 30 30 30 

Map(`/`, fl, 1000) 

# [[1]] 
#  [,1] [,2] [,3] [,4] [,5] [,6] 
# [1,] 0.003 0.003 0.003 0.003 0.003 0.003 
# [2,] 0.003 0.003 0.003 0.003 0.003 0.003 
# [3,] 0.003 0.003 0.003 0.003 0.003 0.003 
# [4,] 0.003 0.003 0.003 0.003 0.003 0.003 
# [5,] 0.003 0.003 0.003 0.003 0.003 0.003 
# 
# [[2]] 
#  [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] 
# [1,] 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03 
# [2,] 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03 0.03 
+0

Для этого необходимо набирать вручную все 1000 списков – user3742038

+0

@ user3742038 показать мне, где я их вручную набрал – rawr

+1

Я нахожусь в крестовом походе, чтобы избавиться от R [строкового типизированного кода] (http://c2.com/cgi/wiki?StringlyTyped) поэтому я хотел бы упомянуть, что R имеет определенный синтаксис для обозначения (иначе недействительных) идентификаторов через \ '' + '\' (т. е. с обратными выводами), и что использование строк здесь, хотя и является допустимым, является странным взломом, не должен * работать, если R имеет правильную систему типов. Тем не менее, хороший ответ. –

0

Я недавно внедренная некоторые рекурсивные функции полезности для этого. Однако они не проверяют предварительные условия (равную длину, суммируемость элементов).

EDIT: Я исправил проблемы, упомянутые в комментариях. Для петель заменяются функциями высокого порядка, и функция имеет лучшее поведение ошибки. Функция также обрабатывает более сложные структуры списка, например. списки, содержащие другие списки, содержащие числовые элементы. Это больше (и сложнее), чем то, о чем попросил ОП, но я подумал, что стоит хранить его на случай, если кому-то понадобится рекурсивное решение.

sum_numeric_lists <- function(...){ 
    lists <- list(...) 

    if (length(unique(sapply(lists, length))) > 1) { 
    stop("lists are not of equal length") 
    } 

    Map(function(...) { 
    elems <- list(...) 
    if (length(unique(sapply(elems, class))) > 1) { 
     stop("corresponding elements have different types") 
    } 
    if (is.list(elems[[1]])) { 
     sum_numeric_lists(...) 
    } else if(is.numeric(elems[[1]])){ 
     Reduce(`+`, elems) 
    } else { 
     warning("lists contain types other than numeric, which are preserved as NULL elements") 
     NULL 
    } 
    }, ...) 

} 


devide_numeric_list_by <- function(l, divisor){ 

    lapply(X = l, FUN = function(elem) { 
    if (is.list(elem)) { 
     devide_numeric_list_by(elem, divisor) 
    } else if(is.numeric(elem)){ 
     elem/divisor 
    } else { 
     warning("lists contain types other than numeric, which are preserved as NULL elements") 
     NULL 
    } 
    }) 

} 

avg_numeric_lists <- function(...){ 
    sum_l <- sum_numeric_lists(...) 
    devide_numeric_list_by(sum_l, length(list(...))) 
} 

Некоторые тесты:

avg_numeric_lists() 
avg_numeric_lists(NULL) 
avg_numeric_lists(list()) 
avg_numeric_lists(list(NULL)) 
avg_numeric_lists(list(1)) 
avg_numeric_lists(list(list(1))) 

list1 <- list(m_first_lvl = matrix(sample(1:10, 20, replace = T), nrow=4, ncol=5),list(m_sec_lvl = matrix(sample(1:10, 6, replace = T), nrow=3, ncol=2)),"not_a_list_or_numeric",a_number = 1) 
list2 <- list(m_first_lvl = matrix(sample(1:10, 20, replace = T), nrow=4, ncol=5),list(m_sec_lvl = matrix(sample(1:10, 6, replace = T), nrow=3, ncol=2)),"not_a_list_or_numeric",a_number = 2) 
list3 <- list(m_first_lvl = matrix(sample(1:10, 20, replace = T), nrow=4, ncol=5),list(m_sec_lvl = matrix(sample(1:10, 6, replace = T), nrow=3, ncol=2)),"not_a_list_or_numeric",a_number = 3) 
avg_numeric_lists(list1, list2, list3) 

Для вызова его на всех списков в глобальной среде (как это было предложено Rawr):

do.call(what = avg_numeric_lists, args = mget(ls(pattern = '^list\\d+$'))) 
+0

это требует ввода во все 1000 списков вручную. – user3742038

+0

Умеете ли вы использовать нижний предел? Я написал этот ответ, прежде чем вы указали, что списки поступают из 1000 файлов .RData ... Но я думаю, что тогда вы останетесь довольны другим ответом. – fab

+2

Я тоже этого не делал, но это не очень хороший код. Это очень трудно прочитать, и петли, вероятно, должны быть заменены соответствующими функциями списка более высокого порядка. Более того, он может извлечь выгоду из правильной обработки ошибок, вместо того, чтобы записывать строки в результат (очень мало случаев, когда это подходит). –

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