2011-01-21 17 views
15

Her biri 10 milyon satır ve 4 sütun içeren iki veri çerçevesi df1 ve df2 var. RODBC/sqlQuery'yi hiçbir problemsiz kullanarak R kullanarak okudum, ancak rbind'u denediğimde bunları en çok R hata iletisinden alıyorum: cannot allocate memory. rbind'u daha verimli bir şekilde yapmak için daha verimli yollar olmalı. Herkesin paylaşmak istedikleri favori kodları var mı? Mesela ben sqldf için doc bu örneği bulundu:R: bellek yetersiz kalmadan iki büyük veri çerçevesinin nasıl kopyalanacağı

# rbind 
a7r <- rbind(a5r, a6r) 
a7s <- sqldf("select * from a5s union all select * from a6s") 

en iyi/önerilen yol yapmak için mi?

GÜNCELLEME Ben JD Uzun anlaşılacağı gibi, dolayısıyla ithalat istenen boyutta bir data.frame oluşturmak için this question

+0

Ön ayırmayı denediniz mi? – aL3xa

+0

İyi fikir - bunu nasıl yapabilirim - memory.limit (size = 4000) 'gibi bir şey kullanmak mı istiyorsunuz? –

+0

No. BTW, yalnızca Windows'ta çalışıyor. Cevabımı aşağıya bakın. – aL3xa

cevap

23

Aksine başında Ar içine okuyarak ve sonra SQLite onları okumak ve R. için dosyaları tek tek

# create two sample files 
DF1 <- data.frame(A = 1:2, B = 2:3) 
write.table(DF1, "data1.dat", sep = ",", quote = FALSE) 
rm(DF1) 

DF2 <- data.frame(A = 10:11, B = 12:13) 
write.table(DF2, "data2.dat", sep = ",", quote = FALSE) 
rm(DF2) 

# now we do the real work 
library(sqldf) 

data1 <- file("data1.dat") 
data2 <- file("data2.dat") 

sqldf(c("select * from data1", 
"insert into data1 select * from data2", 
"select * from data1"), 
dbname = tempfile()) 

R. yüklenen asla bu şekilde göndermeden önce bunları birleştirmek olabilir birleştirerek daha Bu veriyor:

sqldf("select * from data1 union select * from data2", dbname = tempfile()) 
: satır sırası önemsiz ise

> sqldf(c("select * from data1", "insert into data1 select * from data2", "select * from data1"), dbname = tempfile()) 
    A B 
1 1 2 
2 2 3 
3 10 12 
4 11 13 

Bu kısa versiyonu da çalışır

Daha fazla bilgi için sqldf ana sayfasına http://sqldf.googlecode.com ve ?sqldf bakın. Dosya biçimi argümanlarına özellikle dikkat ettikleri için, read.table ile aynı değillerdir. Burada varsayılanları kullandık, bu yüzden daha az sorun yaşadık.

+0

Temiz bir yaklaşım ... SQL kesinlikle büyük bir şey çiğneme yeteneğine sahiptir! – aL3xa

+0

Çok kullanışlı, teşekkürler @Gabor ... Ben gerçek bir SQL veritabanında veri var ve bir sorgu ile tüm şey okurken ben ilk 'RODBC/sqlquery kullanılarak R içine her yarım okumak zorunda yüzden hafızamı, hortum oldu (Bana herşeyi neden boğulduğunu sorma ama her yarımı okuduğumda boğulma). Ama benim asıl veriler iki düz dosyalarda ise, seninki onları okumak, ve R bellekte iki bölümden zorunda kalmamak için en iyi yoldur kabul ediyorum. –

1

deneyin için onun cevabını, yukarıda sqldf çağrısında önemli dbname = tempfile() argümanı kullanarak çalışmak lazım verilerinizi abonelikler kullanarak.

dtf <- as.data.frame(matrix(NA, 10, 10)) 
dtf1 <- as.data.frame(matrix(1:50, 5, 10, byrow=TRUE)) 
dtf2 <- as.data.frame(matrix(51:100, 5, 10, byrow=TRUE)) 
dtf[1:5, ] <- dtf1 
dtf[6:10, ] <- dtf2 

Ben rbind boyutlarını önceden tahsis etmeden nesneyi büyür tahmin ... Ben bu sadece bir tahmin olduğunu, olumlu emin değilim. Bu gece "The R Inferno" veya "R ile Veri Manipülasyonu" nu indireceğim. Belki merge

DÜZENLEME

... hile olacaktır Ve (belki) sistem ve/veya R şey büyük bununla başa çıkamaz akılda çıplak olmalıdır. RevolutionR'ı dene, belki biraz zaman/kaynak ayırmayı başarabilirsin.

+0

İlginç bir öneri, teşekkürler. Denerim. –

+1

ilginç öneri (Revo benim için bir seçenek değildir bu yüzden olsa özgür Ar ötesine gitmek istemiyorum) ama rbind çok daha fazla bellek kullanır. –

15

Birkaç milyondan fazla kaydı olan nesneler üzerinde verimli işlemler için data.table R paketine dikkat edin.

Bu paketin 1.8.2 sürümü, çok verimli bir şekilde istediğinizi elde edebileceğiniz rbindlist işlevini sunar. Böylece yerine rbind(a5r, a6r) arasında şunları yapabilirsiniz: birliğin konu hakkında bu thread Bütünlüğü için

library(data.table) 
rbindlist(list(a5r, a6r)) 
+1

öncelikle belleğe veri kümesi yüklemeden bunu yapabilir mi? – panterasBox

1

: büyük dosyaları ing, bunları birleştirmek için dosyalar üzerinde kabuk komutlarını kullanmayı deneyin. "/ B" bayrağıyla "COPY" komutu olan pencerelerde.Örnek: veri akışları dışarı eşlerken

system(command = 
     paste0(
      c("cmd.exe /c COPY /Y" 
      , '"file_1.csv" /B' 
      , '+ "file_2.csv" /B' 
      , '"resulting_file.csv" /B' 
      ), collapse = " " 
     ) 
)#system 

dosyalar başlık ve aynı sınırlayıcı vs vs hız ve kabuk komutları yönlülüğü bazen büyük bir avantajdır sahip olmanızı gerektirir, böylece CLI-komutları unutma.

İlgili konular