2011-05-12 18 views
8

Tümünün en az bir satır içerdiğinden emin olduğum bir veri çerçeve listesi var (aslında, bazıları yalnızca bir satır içerir ve diğerleri belirli sayıda satır içerir) ve hepsinin aynı sütunlara sahip olması (isimler ve tipler). Durumun önemli olması durumunda, satırlarda hiçbir NA'nın bulunmadığından eminim. rbind.data.frame ürününün performansı

durum

böyle simüle edilebilir: onlar benim gerçek durumu yansıttığı böylece (randomizasyon) parametrelerini ayarlamak ettik

#create one row 
onerowdfr<-do.call(data.frame, c(list(), rnorm(100) , lapply(sample(letters[1:2], 100, replace=TRUE), function(x){factor(x, levels=letters[1:2])}))) 
colnames(onerowdfr)<-c(paste("cnt", 1:100, sep=""), paste("cat", 1:100, sep="")) 
#reuse it in a list 
someParts<-lapply(rbinom(200, 1, 14/200)*6+1, function(reps){onerowdfr[rep(1, reps),]}) 

.

Tüm bu veri çerçevelerini tek bir veri çerçevesinde birleştirmek istiyorum. Böyle, hile yapacağını rbind kullanarak düşündüm:

system.time(
result<-do.call(rbind, someParts) 
) 

Şimdi benim sistemde (özellikle yavaş değil) ve yukarıdaki ayarlarla bu system.time çıktısı alır:

user system elapsed 
    5.61 0.00 5.62 

Rastgele 254 (benim durumumda) 200 değişkenli satır için yaklaşık 6 saniye? Şüphesiz, buradaki performansı iyileştirmenin bir yolu olmalı? Benim kodumda, sık sık benzer şeyleri yapmak zorundayım (bu, birden fazla ithamdan kaynaklanmaktadır), bu yüzden mümkün olduğunca hızlı olmak için buna ihtiyacım var.

+0

, ben burada Dominik http://stackoverflow.com/questions/7224938/can-i-rbind-be-parallelized-in-r/8071176#8071176 bir teknik kullanılarak dataframes listesini kombine Olduğundan daha hızlıdır, daha büyük olduğu ve orijinal liste verisini faktörler yerine karakterlerle okuduğumda daha iyi bir performans buldu. Rbind kullanarak eşleşme çok zaman harcadı; Eklemek için faktör düzeylerini kontrol etmek için spekülasyon yapıyorum. – ARobertson

cevap

13

Matrislerinizi yalnızca sayısal değişkenlerle oluşturabilir ve sonunda bir faktöre dönüştürebilirsiniz? rbind sayısal matrislerde çok daha hızlıdır. veri çerçevelerini kullanarak sistemde

: Bunun yerine tüm sayısal matrisleri listeyi Bina

> system.time(result<-do.call(rbind, someParts)) 
    user system elapsed 
    2.628 0.000 2.636 

: Daha hızlı rbind bir çok

onerowdfr2 <- matrix(as.numeric(onerowdfr), nrow=1) 
someParts2<-lapply(rbinom(200, 1, 14/200)*6+1, 
        function(reps){onerowdfr2[rep(1, reps),]}) 

sonuçlanır.

> system.time(result2<-do.call(rbind, someParts2)) 
    user system elapsed 
    0.001 0.000 0.001 
DÜZENLEME: İşte başka bir olasılık; Her sütunu sırayla birleştirir.
> system.time({ 
+ n <- 1:ncol(someParts[[1]]) 
+ names(n) <- names(someParts[[1]]) 
+ result <- as.data.frame(lapply(n, function(i) 
+       unlist(lapply(someParts, `[[`, i)))) 
+ }) 
    user system elapsed 
    0.810 0.000 0.813 

Yine de matrisleri kullanmanın neredeyse o kadar hızlı değil.

DÜZENLEME 2: Yalnızca sayısal değerler ve faktörleri varsa

, bu rbind, sayısal onları her şeyi dönüştürmek ve faktörlere geri gerekli sütunlar dönüştürmek o kadar da zor değil. Bu, tüm faktörlerin tam olarak aynı seviyelere sahip olduğunu varsayar. Bir tam sayıdan bir faktöre dönüştürme de sayısaldan daha hızlıdır, bu yüzden önce tamsayıya zorlar.

user system elapsed 
    0.090 0.00 0.091 
+1

@Aaron: Veriler bir simülasyon, OP'nin dataframes ile başlattığı soru. –

+0

@Joris: Yakın; Her türün kendi matris listesinden çıkarılabileceğini, her tip listesindeki rbind'i sonra da bir data.frame oluşturabileceğini. –

+0

@Joris: Doğru, bu, posterin özel sorusuna cevap vermiyor (rbind.data.frame'i nasıl hızlandırabilirim?). Fakat belki de, matrislerin matriksinin daha hızlı olduğu bilgisiyle, veri çerçevelerini kullanmaktan kaçınmak için kodunu yeniden yazabilir veya daha sonra veri karelerine dönüştürebilir. Aslında 'rbind.data.frame' hızlandırmak için yollar görmek isterim. – Aaron

5

Değil çok büyük bir destek ama plyr paketinden rbind.fill için rbind takas üzerinde, örnek veri kümesi ile (çalışma süresi kapalı yaklaşık% 10 darbelere:

someParts2 <- lapply(someParts, function(x) 
        matrix(unlist(x), ncol=ncol(x))) 
result<-as.data.frame(do.call(rbind, someParts2)) 
a <- someParts[[1]] 
f <- which(sapply(a, class)=="factor") 
for(i in f) { 
    lev <- levels(a[[i]]) 
    result[[i]] <- factor(as.integer(result[[i]]), levels=seq_along(lev), labels=lev) 
} 

sistemimde zamanlama benim makinem).

3

Bu,% 25 daha hızlı, ama daha iyi bir yolu olmalı ...Eğer gerçekten hızlı data.frame s işlemek istiyorsanız

system.time({ 
    N <- do.call(sum, lapply(someParts, nrow)) 
    SP <- as.data.frame(lapply(someParts[[1]], function(x) rep(x,N))) 
    k <- 0 
    for(i in 1:length(someParts)) { 
    j <- k+1 
    k <- k + nrow(someParts[[i]]) 
    SP[j:k,] <- someParts[[i]] 
    } 
}) 
+0

Montaj kodunda yeniden yazma? –

+0

Bunu yapılandırarak, veri çerçevesinin sütunlarını her bir öğeden uygun bir sütunu "lapply" ile kaplayarak sütuna göre doldurmayı denedim; Hala daha hızlı görünüyor. Cevabım için düzenle konusuna bakın. – Aaron

4

, ben paketi data.table ve işlevini rbindlist() kullanmak öneririm. Kapsamlı testler yapmadım ama veri kümem için (3000 veri karesi, her biri 1000 satır x 40 sütun) rbindlist() sadece 20 saniye sürüyor.

1

Veri çerçevesini veri alanına bağladığınızdan emin olun. Veri çerçevesine bağlantı verildiğinde büyük bir bozulmaya neden oldu. İşimde

İlgili konular