आर

2012-03-01 8 views
66

में दो सूचियाँ मर्ज मैं दो सूचियोंआर

first = list(a = 1, b = 2, c = 3) 
second = list(a = 2, b = 3, c = 4) 

मैं इन दोनों सूचियों विलय करने के लिए तो अंतिम उत्पाद

$a 
[1] 1 2 

$b 
[1] 2 3 

$c 
[1] 3 4 

है चाहता हूँ वहाँ यह करने के लिए एक सरल समारोह है है?

both <- list(first, second) 
n <- unique(unlist(lapply(both, names))) 
names(n) <- n 
lapply(n, function(ni) unlist(lapply(both, `[[`, ni))) 

और दूसरा, जो काम करता है केवल अगर वे एक ही संरचना है::

apply(cbind(first, second),1,function(x) unname(unlist(x))) 

दोनों वांछित परिणाम

+0

की जांच: http://stackoverflow.com/questions/7349608/merge-contents-within-list-of-list-by-duplicate-name – Hansi

उत्तर

94

सूचियों हमेशा उदाहरण के रूप में एक ही संरचना, है, तो एक सरल समाधान

mapply(c, first, second, SIMPLIFY=FALSE) 
+26

यदि कोई परवाह करता है तो यह 'मानचित्र (सी, पहला, दूसरा) 'के बराबर है। – Masterfool

+2

मैं सिर्फ आर सीख रहा हूं, मानचित्र (और मैप्ली) में पहले पैरामीटर के रूप में 'सी' क्यों है? क्या पैरामीटर बस दो सूचियों में पारित नहीं होना चाहिए? – user391339

+2

'सी' एक प्राचीन कार्य का नाम है जो सूचियां बनाता है। पीछे वाले माता-पिता के बिना आर में टाइपिंग सी 'फ़ंक्शन (..., रिकर्सिव = गलत) दिखाती है। ("सी")' तो यह क्लिच 'सी' फ़ंक्शन को पहले और दूसरे की सामग्री पर मैप कर रहा है। –

12

यहाँ दो विकल्प हैं, पहला है।

+0

मैं अपने दूसरे में नहीं सोचता एक सही ढंग से काम करता है क्योंकि मुझे वैक्टर की सूची के बजाय मैट्रिक्स डिज़ाइन मिलता है। –

+0

आप सही हैं; 'लागू करें' इसे सरल बनाता है अगर यह कर सकता है। यह काम करता है अगर यह सरल नहीं हो सकता है, जैसे कि 'पहले $ सी <- सी (4,5) 'उदाहरण के लिए। – Aaron

+0

पहला मुझे लंबाई = 0 की एक सूची देता है। नाम कुछ के रूप में परिभाषित किया जाना चाहिए? –

23

यह सरकार द्वारा modifyList समारोह के एक बहुत ही सरल अनुकूलन है। चूंकि यह पुनरावर्ती है, यह mapply की तुलना में अधिक जटिल स्थितियों को संभालेगा, और यह 'दूसरे' में मौजूद वस्तुओं को अनदेखा करके बेमेल नाम स्थितियों को संभालेगा जो 'पहले' में नहीं हैं।

appendList <- function (x, val) 
{ 
    stopifnot(is.list(x), is.list(val)) 
    xnames <- names(x) 
    for (v in names(val)) { 
     x[[v]] <- if (v %in% xnames && is.list(x[[v]]) && is.list(val[[v]])) 
      appendList(x[[v]], val[[v]]) 
     else c(x[[v]], val[[v]]) 
    } 
    x 
} 

> appendList(first,second) 
$a 
[1] 1 2 

$b 
[1] 2 3 

$c 
[1] 3 4 
4

यहां कुछ कोड है जो मैंने एंड्रॉइड के उत्तर पर आधारित लेकिन गठबंधन/सादगी के आधार पर लेखन समाप्त कर दिया है।

v1 <- list("a"=c(1,2), b="test 1", sublist=list(one=20:21, two=21:22)) 
v2 <- list("a"=c(3,4), b="test 2", sublist=list(one=10:11, two=11:12, three=1:2)) 
mergeLists(v1, v2) 

यह:

# Decided to move this outside the mapply, not sure this is 
# that important for speed but I imagine redefining the function 
# might be somewhat time-consuming 
mergeLists_internal <- function(o_element, n_element){ 
    if (is.list(n_element)){ 
    # Fill in non-existant element with NA elements 
    if (length(n_element) != length(o_element)){ 
     n_unique <- names(n_element)[! names(n_element) %in% names(o_element)] 
     if (length(n_unique) > 0){ 
     for (n in n_unique){ 
      if (is.matrix(n_element[[n]])){ 
      o_element[[n]] <- matrix(NA, 
            nrow=nrow(n_element[[n]]), 
            ncol=ncol(n_element[[n]])) 
      }else{ 
      o_element[[n]] <- rep(NA, 
            times=length(n_element[[n]])) 
      } 
     } 
     } 

     o_unique <- names(o_element)[! names(o_element) %in% names(n_element)] 
     if (length(o_unique) > 0){ 
     for (n in o_unique){ 
      if (is.matrix(n_element[[n]])){ 
      n_element[[n]] <- matrix(NA, 
            nrow=nrow(o_element[[n]]), 
            ncol=ncol(o_element[[n]])) 
      }else{ 
      n_element[[n]] <- rep(NA, 
            times=length(o_element[[n]])) 
      } 
     } 
     } 
    } 

    # Now merge the two lists 
    return(mergeLists(o_element, 
         n_element)) 

    } 
    if(length(n_element)>1){ 
    new_cols <- ifelse(is.matrix(n_element), ncol(n_element), length(n_element)) 
    old_cols <- ifelse(is.matrix(o_element), ncol(o_element), length(o_element)) 
    if (new_cols != old_cols) 
     stop("Your length doesn't match on the elements,", 
      " new element (", new_cols , ") !=", 
      " old element (", old_cols , ")") 
    } 

    return(rbind(o_element, 
       n_element, 
       deparse.level=0)) 
    return(c(o_element, 
      n_element)) 
} 
mergeLists <- function(old, new){ 
    if (is.null(old)) 
    return (new) 

    m <- mapply(mergeLists_internal, old, new, SIMPLIFY=FALSE) 
    return(m) 
} 

यहाँ मेरी उदाहरण है: लाभ यह है कि यह एक अधिक जटिल पुनरावर्ती मर्ज की अनुमति देता है और यह भी तत्वों है कि rbind साथ जोड़ा जाना चाहिए और उन है कि सिर्फ c साथ जुड़े हुए हैं के बीच अलग है में परिणाम:

$a 
    [,1] [,2] 
[1,] 1 2 
[2,] 3 4 

$b 
[1] "test 1" "test 2" 

$sublist 
$sublist$one 
    [,1] [,2] 
[1,] 20 21 
[2,] 10 11 

$sublist$two 
    [,1] [,2] 
[1,] 21 22 
[2,] 11 12 

$sublist$three 
    [,1] [,2] 
[1,] NA NA 
[2,] 1 2 

हाँ, मुझे पता है - शायद नहीं सबसे तार्किक मर्ज लेकिन मैं एक जटिल समानांतर पाश है कि मैं हा घ के लिए एक अधिक अनुकूलित .combine समारोह उत्पन्न करने के लिए है, और इसलिए मैं इस राक्षस लिखा :-)

1

सामान्य से एक सकता है में,

merge_list <- function(...) by(v<-unlist(c(...)),names(v),base::c) 

ध्यान दें कि by() समाधान एक attribute घ सूची लौटाती है, तो यह प्रिंट होगा अलग-अलग, लेकिन अभी भी एक सूची होगी। लेकिन आप attr(x,"_attribute.name_")<-NULL के साथ विशेषताओं से छुटकारा पा सकते हैं। आप शायद aggregate() का भी उपयोग कर सकते हैं।

3

list3 <- append(list1, list2) भी काम करेंगे