2013-06-19 57 views
3

我有在每個data.frames的多列data.frames的列表。每個data.frame具有相同的結構。另外我有另外一個包含多個data.frames的列表。兩個列表與多列的條件匹配data.frames

比方說,這是兩個列表:

firstlist <- list(a=data.frame(AA=5:1, 
         BB=1:5), 
      b=data.frame(AA=5:1, 
         BB=1:5), 
      c=data.frame(AA=5:1, 
         BB=1:5)) 
secondlist <- list(a=data.frame(AA=1:10, 
         BB=c(0,0,1,0,0,1,1,0,0,0)), 
      b=data.frame(AA=1:10, 
         BB=c(0,1,0,0,0,0,1,0,0,0)), 
      c=data.frame(AA=1:10, 
         BB=c(1,0,0,0,0,1,1,0,0,0))) 

現在我想列CC添加到所有data.frames在firstlist並填寫相應他們從secondlist列BB值。

的問題是:我需要檢查,如果從firstlist AA或BB的行包含從AA中secondlist的價值,並與BB在secondlist值填寫firstlist新列CC。

與示例數據預期的結果上面會:

> firstlist 
$a 
    AA BB CC 
    1 5 1 0 
    2 4 2 0 
    3 3 3 1 
    4 2 4 0 
    5 1 5 0 

$b 
    AA BB CC 
    1 5 1 0 
    2 4 2 1 
    3 3 3 0 
    4 2 4 1 
    5 1 5 0 

$c 
    AA BB CC 
    1 5 1 1 
    2 4 2 0 
    3 3 3 0 
    4 2 4 0 
    5 1 5 1 

我需要使用for循環或者是有任何其他方式?

更新: 對於所有數據類型,請參閱Thell's solution以獲取所有數據類型的數據,並使用eddie's solution

預先感謝您!

+0

你能告訴我們你的數據預期的結果?第一部分是有點不清楚,我...「我需要檢查,如果從firstlist在AA或BB的行...」 – Arun

+0

@Arun我編輯了問題。增加了預期的結果。 換句話說: 我需要檢查是否在列AA或BB任何行firstlist的每一個data.frame包含相同的值命名data.frame secondlist同一列AA一行。如果是這樣,我需要填充第一列表中的新列CC和第二列表中BB的相應值。這聽起來更加貼切,但我不知道如何更好地描述它。 – Nikita

+1

$ b列'CC'' 0,1,0,1,0'如何?你能解釋一下嗎? – Arun

回答

2

如果CC是真正的布爾...

f <- function(a,b) cbind(a, CC=b$BB[ match(a$AA, b$AA) ] | 
           b$BB[ match(a$BB, b$AA) ] ) 
mapply(f, firstlist, secondlist, SIMPLIFY=F) 

直線前進,快速,並保持名稱...

基準示例vs lapply版本::

Unit: milliseconds 
      expr  min  lq median  uq  max neval 
    this mapply 1.726471 1.840671 1.870504 1.939473 13.88875 100 
Arun's lapply 2.930061 3.048110 3.134402 3.209786 14.61630 100 
+0

+1非常不錯的加法。 – Arun

1
lapply(seq_along(firstlist), 
     function(i) { 
     d.1 = merge(firstlist[[i]], secondlist[[i]], by = "AA", sort = FALSE) 
     names(d.1) = c("AA", "BB", "CC") 
     d.2 = suppressWarnings(merge(firstlist[[i]], secondlist[[i]], by.x = "BB", by.y = "AA", sort = FALSE)) 
     names(d.2) = c("BB", "AA", "CC") 
     d.1$CC = 0 + (d.1$CC | d.2$CC) 
     d.1 
     }) 

您可能想重命名上面的列而不是禁止警告。

+1

我認爲比這個更復雜,因爲您不會爲第一個列表中與BB列匹配的人重複條目。 – dickoa

+0

是的,這段代碼沒有考慮到BB表格firstlist。 它也不保留data.frames和列的名稱。 但它可能是一個很好的開始。 – Nikita

+0

@dickoa我看,謝謝,修復 – eddi

2

這裏的另一種相對較短的方式(假設BBsecondlist是二進制的(只有0和另一個值):

lapply(seq_along(firstlist), function(ix) { 
    tt <- secondlist[[ix]][secondlist[[ix]]$BB != 0, ] 
    transform(firstlist[[ix]], CC = 1 * (firstlist[[ix]]$AA %in% tt$AA | 
     firstlist[[ix]]$BB %in% tt$AA)) 
}) 
+0

這也適用!我會去適應這一點。 – Nikita

+0

謝謝!因爲它是二元的,所以它工作得很好。只有一個化妝品問題:有沒有辦法保留'firstlist'的'名字'?我可以恢復它們,因爲它們也存儲在一個額外的矢量中,但保存它們會很好。 – Nikita

+1

你可以用'setNames()'來包裝'lapply':'out < - setNames(lapply(...),names(firstlist))' – Arun