2015-04-23 16 views
7

ile R birleştirme Ben iki data.tables: samples, resourcesÇapraz/Yeni gruplama birleştirme/data.table en X [E] şeklini

resourcesprimary ve secondary kimlikleri ile samples ile bağlanır. Kaynaklardan gelen bilgileri öncelikle birincil tabloyu kullanarak örnek tablo ile birleştirmek istiyorum ve bu yalnızca NA üretiyorsa, o zaman aynı tablodaki ikincil kaynaklara başvurmak istiyorum (bir data.table komut zincirinde) .

# resources: 
    primary secondary info 
1:  17  42 "I" 
2:  18  NA "J" 
3:  19  43 "K" 

# samples: 
    name primary secondary 
1: "a"  17  55 
2: "b"  0  42 
3 "c"  18  42 

istenen sonucu olacaktır: primary aracılığıyla

# joined tables: 
    name info # primary secondary 
1: "a" "I" 
2: "b" "I" 
3: "c" "J" 

ilk olarak katılmak daha sonra

# Update: 
samples <- data.table(name = letters[1:3], 
         primary = c(17, 0, 18), 
         secondary = c(55, 42, 42)) 
resources <- data.table(primary = 17:19, 
         secondary = c(42, NA, 43), 
         info = LETTERS[9:11]) 
# first join: 
setkey(samples, primary) 
setkey(resources, primary) 
samples[resources] 

    name info # primary secondary 
1: "a" "I" 
2: "b" NA 
3: "c" "J" 

Ama üretir, kolay? setkey(samples, secondary) ile örnekleri yeniden anahtarlamam gerekiyor, değil mi? Ve sonra sadece NA'ları üreten satırlara ayırın. Ancak bütün bunlar bir komuta zincirinde gerçekten mümkün değildir (ve iki kriterin birden fazla olduğunu hayal edin ...). Bunu daha kısa sürede nasıl başarabilirim?

... data.tables koduyla güncellendi.

+6

Belki de 'örnekler' ve 'kaynakları' yapılarını oluşturan kodları dahil ederek kolayca yeniden üretilebilir hale getirin? –

+0

'data.table' dostu değil, ancak yararlı olması durumunda: http: // stackoverflow.com/questions/11369837/nasıl yapılır-nasıl-koşullu-left-join-in-r – npjc

+2

tek bir komut zincirinde yapmak isteyen yanlış yönlendirilmiş – eddi

cevap

5

Tek bir satırda yapabiliyor olsanız da, yaptığınız şeyin anlamını gizlediğini düşünüyorum, bir ay içinde yaptığınız şeyi okumak/anlamak/hata ayıklamak/hatırlamak için son derece zor bir şey yapar ve sadece bir kötü bir fikir. @nachti Açıklamalarda belirttiği gibi

setkey(samples, primary) 
setkey(resources, primary) 
samples[resources, info := i.info] 

setkey(samples, secondary) 
setkey(resources, secondary) 
samples[resources, info := ifelse(is.na(info), i.info, info)] 

samples 
# name primary secondary info 
#1: b  0  42 I 
#2: c  18  42 J 
#3: a  17  55 I 

# keep going with tertiary and so on if you like 

, kendi verilerine bağlı olarak 1.9.5 öncesi sürümler için allow.cartesian=TRUE eklemeniz gerekebilir:

Daha küçük, daha kolay sindirilebilir parçalar imo gitmek için bir yoldur .

+3

Bunu ilk bir satırda bir ton şey yapmak lazım, zincirleme/boru tesisatı keşfetmek zaman, serin, ama o ilk heyecan etkisini kaybetmesinden sonra, geri ölçek ve aslında yok senin bütününü istiyorum gerçekleştirmek gerekir var olsun tek bir satırda betik. 'Için daha fazla bilgi: [.EACHI by =, = ifelse (is.na (bilgi), i.info, bilgi) kaynakları, bilgi]' örnekleri: – eddi

+0

Sen dt 1.9.4 beri = .EACHI' tarafından 'eklemek zorunda https://github.com/Rdatatable/data.table/blob/master/README.md adresine bakın – nachti

+0

@nachti no, bu yanlış - yukarıdaki 1.9.5 kullanılarak çalıştırıldı ("var" bölümü yanlış - siz * * ekleyebilirsiniz, ancak bu sonuç değişmeyecek ve o veya bir performans farkı neden olabilir veya olmayabilir - F__ (Ben vecseq içinde hata olsun 1.9.4 yılında – eddi

1

Ben tek bir komut zinciri içinde bunu yapmak için çok zor olduğunu düşünüyorum, ama senin için bir çözüm var:

### First step 
samples[resources[samples, nomatch = 0], info := info] 
samples 

    name primary secondary info 
1: b  0  42 NA 
2: a  17  55 I 
3: c  18  42 J 

### Second step 
setkey(samples, secondary) 
setkey(resources, secondary) 
## create new column info1 
samples[resources[samples[is.na(info)], 
        list(info1 = unique(info)), by = .EACHI], 
     info1 := info1] 
## merge it to samples, where info is NA 
samples[is.na(info), info := info1] 
## remove info1 (and maybe other unused columns) 
samples[, info1 := NULL] 
## sort samples by name 
setkey(samples, name) 
samples 

    name primary secondary info 
1: a  17  55 I 
2: b  0  42 I 
3: c  18  42 J 

hth
~ Bu 2 çağrıları ile bir zincir olacağını

2

gr resources, bunlardan biri sahne arkasında yeniden setkey.

library(data.table) 
samples <- data.table(name = letters[1:3], 
         primary = c(17, 0, 18), 
         secondary = c(55, 42, 42)) 
resources <- data.table(primary = 17:19, 
         secondary = c(42, NA, 43), 
         info = LETTERS[9:11]) 
setkey(samples, primary) 
setkey(resources, primary) 
samples[resources, info := i.info 
     ][, .(name, info),, secondary 
      ][resources[, info,, secondary], info := ifelse(is.na(info), i.info, info) 
      ][, secondary := NULL] 

daha karmaşık örnekler hakkında soruyorsunuz gibi. Data.table sorgularının, alt sorgu argümanlarını önceden hazırlayarak modüller olarak kolayca yönetilebileceğini not etmeye değer. Daha sonra kolayca şartlı olarak yönetilebilirler. Aşağıdaki örneğe bakınız.

lkp2 <- quote(resources[, info,, secondary]) 
lkp2_formula <- quote(info := ifelse(is.na(info), i.info, info)) 
setkey(samples, primary) 
samples[resources, info := i.info 
     ][, .(name, info),, secondary 
      ][eval(lkp2), eval(lkp2_formula) 
      ][, secondary := NULL] 

Eğer ağır data.table zincirleme itimat Eğer dtq paket kullanışlı bulabilir işler.

+1

"i" ve "j" komutlarını ayrı ayrı tanımlama öneriyi beğeniyorum, bu da kodun daha karmaşık durumlarda okunmasını kolaylaştırmaya yardımcı olabilir. Bu stratejiyi @eddi ve @nachti'nin önerileriyle birleştireceğim. – Wordsmyth