2015-07-24 2 views
2

Это то, что я пытаюсь сделать. Мне нужно написать функцию, назовем ее combine, которая занимает несколько списков и объединяет их. Чтобы передать несколько списков функции, мне нужно использовать эллипсис в качестве аргумента для функции. Я не могу понять, как правильно комбинировать списки внутри функции.Функция объединения нескольких списков по факторам в R

Списки (все из которых имеют общую структуру), которые будут переданы функции, имеют несколько факторов, некоторые из которых являются матрицами и другими числовыми векторами. Так, например, списки выглядят

 list1 <- list(a= matrix(), b=numeric(), c=numeric()) 

мне нужно определить такую ​​функцию:

combine <- function(...) { 

     #get all lists as lists or something that is convenient 
     all_lists <- list(...) 

     #define a list which will be returned 
     l <- list(a= list(), b=numeric(), c=numeric()) 

     #l$a <- combine factor 'a' of all input lists as lists, use list() 
     #l$b <- cbind factor 'b' of all input lists as data frame, use cbind() 
     #l$c <- set union of elements of factor 'c' of input lists, use union() 

     return(l) 
    } 

Так что, если я прохожу три списка функции, выход должен быть как

>l1 <- list(a= matrix(c(1:20), 10,2), b=c(1:11), c= c(1:5)) 
    >l2 <- list(a= matrix(c(21:40), 10,2), b=c(11:21), c= c(2:7)) 
    >l2 <- list(a= matrix(c(41:60), 10,2), b=c(21:31), c= c(3:6)) 

    >l <- combine(l1, l2, l3) 
    >l$a[1] 
    [[1]] 
      [,1] [,2] 
    [1,] 1 11 
    [2,] 2 12 
    [3,] 3 13 
    [4,] 4 14 
    [5,] 5 15 
    [6,] 6 16 
    [7,] 7 17 
    [8,] 8 18 
    [9,] 9 19 
    [10,] 10 20 
    > l$b[4,3] 
    [1] 24 
    > l$c 
    [1] 1 2 3 4 5 6 7 

Любая помощь будет высоко оценена.

+0

да, но 'c' просто связывает все списки вместе, он не делает вид переформатирования факторов, которые моя функция должна делать. –

ответ

3

вы можете использовать lapply, чтобы просмотреть все списки и извлечь из них a, b или c и объединить эти списки, как вам нужно. У тебя; для b вы можете использовать do.call('cbind', ...) до cbind список вещей; и с просто union или получить все уникальные элементы

l1 <- list(a= matrix(c(1:20), 10,2), b=c(1:11), c= c(1:5)) 
l2 <- list(a= matrix(c(21:40), 10,2), b=c(11:21), c= c(2:7)) 
l3 <- list(a= matrix(c(41:60), 10,2), b=c(21:31), c= c(3:6)) 

combine <- function(...) { 
    all_lists <- list(...) 
    l <- list() 
    l$a <- lapply(all_lists, '[[', 'a') 
    l$b <- do.call('cbind', lapply(all_lists, '[[', 'b')) 
    l$c <- Reduce(union, lapply(all_lists, '[[', 'c')) 
    ## or 
    # l$c <- unique(unlist(lapply(all_lists, '[[', 'c'))) 
    l 
} 

l <- combine(l1, l2, l3) 

l$a[1] 
# [[1]] 
#  [,1] [,2] 
# [1,] 1 11 
# [2,] 2 12 
# [3,] 3 13 
# [4,] 4 14 
# [5,] 5 15 
# [6,] 6 16 
# [7,] 7 17 
# [8,] 8 18 
# [9,] 9 19 
# [10,] 10 20 

l$b[4,3] 
# [1] 24 

l$c 
# [1] 1 2 3 4 5 6 7 
+0

Благодарим вас за ответ. Можете ли вы рассказать о том, что «[[' 'делает? Похоже, вы используете его как функцию, но я не знал, что его можно использовать как функцию. –

+0

@MrK все в r является функцией. попробуйте это: '\' [\ '(c ('a', 'b'), 2)' как я использовал '[[' просто коротко для чего-то вроде 'lapply (all_lists, function (x) x [[ 'с']]) '. что может быть проще увидеть, что происходит, но с другой стороны избавит вас от необходимости использовать анонимную функцию и выглядит немного чище IMO – rawr

+0

ooh, спасибо за разъяснение! –

2

Я не вижу, как ваш желаемый результат пришел быть, но, по вашему вопросу, вот функция, которая выполняет следующие действия:

  • Взять слот a каждого списка и связать их все в списке.
  • Сделайте слот b каждого списка и привяжите его к матрице.
  • Сделайте слот c каждого списка и объедините.

combine <- function(...) { 

    #get all lists as lists or something that is convenient 
    all_lists <- list(...) 

    la <- lapply(all_lists, function(x) x$a) 
    lb <- sapply(all_lists, function(x) x$b) 
    lc <- unique(do.call(c,sapply(all_lists, function(x) x$c))) 

    #define a list which will be returned 
    return(list(a=la,b=lb,c=lc)) 
} 

l1 <- list(a= matrix(c(1:20), 10,2), b=c(1:11), c= c(1:5)) 
l2 <- list(a= matrix(c(21:40), 10,2), b=c(11:21), c= c(2:7)) 
l3 <- list(a= matrix(c(41:60), 10,2), b=c(21:31), c= c(3:6)) 

combine(l1,l2,l3) 
+0

Я только что дал образец того, что я ожидал от желаемого результата. Перед вашим ответом это не возникло. :) Кроме того, вы пропустили цитаты вокруг 'c' в' do.call'. Спасибо за ответ. Я пытался использовать лап, но мне не приходило в голову, что я могу просто вернуть соответствующие факторы. –

+0

@MrK - Разве я? Я считаю, что 'do.call' не нуждается в котировках в этом случае. Достаточно назвать функцию здесь, см. '? Do.call'. – SimonG

+0

Хмм. ну, я получил ошибку, когда я попробовал свой код. Итак, я поставил 'c' в кавычки, и это сработало. –

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