2012-02-10 18 views
28

2 ile 20 arasındaki sütunlarda boşluk içeren dizelerle (ör., "Tür Adı") data.table var. Tüm bu sütunlarda aynı anda str_replace()'u çalıştırmak istiyorum, böylece tüm "Tür Adı", "Species_Name" olur.Bir data.table uygulamasında nasıl çalışırım?

data.table(apply(as.data.frame(dt[,2:dim(dt)[2], with=F]), 2, 
           function(x){ str_replace(x," ","_") })) 

ya ben data.table nesne olarak tutarsan, o zaman ben bir anda bu bir sütun yapabilirsiniz: Yapabileceğim ya tüm sütunlar 2 ile için bunu nasıl

dt[,SpeciesName := str_replace(SpeciesName, " ", "_") 

Yukarıdakilerden birine benzer mi?

cevap

30

Tamamen 2015-11-24 tamamen yeniden tasarlanan, önceki sürümlerinde bir hatayı düzeltmek için.

Birkaç seçeneğiniz var. yerinde modifiye değerlerini atamak için := kullanılarak lapply() için

  1. Süreç gömülü çağrısıyla hedef sütunları bütün bunların. Bu , LHS'de adlandırılmış birkaç sütuna eş zamanlı olarak atamak için çok kullanışlı bir destek olan :='a dayanır.

  2. kullanın for döngü hedef sütunları sırayla her birinin değerini değiştirmek için set() kullanarak aynı anda bir, geçmek için.

  3. kullanın for döngü, her biri tek bir sütun modifiye , [.data.table() çağrıları birden çok "naif" yineleme için.

Bu yöntemler hepsi eşit hızlı hakkında görünüyor, bu nedenle hangisini tadı çoğunlukla bir mesele olacaktır kullanın. (1) güzel kompakt ve ifade eder. En sık kullandığım şey, (2) okumayı daha kolay bulabilir. Sütunları tek tek işledikleri ve değiştirdikleri için, (2) veya (3) verilerinizin çok az olduğu bir durumda bir avantajı olacaktır. Bu nedenle, sizin tarafınızdan verilen limitlerine karşı koşma tehlikesi vardır. R oturumu kullanılabilir bellek. set() ve := ilgili ayrıntılı bilgi için

library(data.table) 

## Create three identical 1000000-by-20 data.tables 
DT1 <- data.table(1:1e6, 
      as.data.table(replicate(1e6, paste(sample(letters, nr, TRUE), 
              sample(letters, nr, TRUE))))) 
cnames <- c("ID", paste0("X", 1:19)) 
setnames(DT1, cnames) 
DT2 <- copy(DT1); DT3 <- copy(DT1) 

## Method 1 
system.time({ 
DT1[, cnames[-1] := lapply(DT1[,cnames[-1],with=FALSE], 
         function(x) gsub(" ", "_", x))] 
}) 
## user system elapsed 
## 10.90 0.11 11.06 

## Method 2 
system.time({ 
    for(cname in cnames[-1]) { 
     set(DT2, j=cname, value=gsub(" ", "_", DT2[[cname]])) 
    } 
}) 
## user system elapsed 
## 10.65 0.05 10.70 

## Method 3 
system.time({ 
    for(cname in cnames[-1]) { 
     DT3[ , cname := gsub(" ", "_", DT3[[cname]]), with=FALSE] 
    } 
}) 
## user system elapsed 
## 10.33 0.03 10.37 

, ?set veya ?":=" yazarak kazanılmış onların yardım sayfasını, okuyun.

+0

Bu ilginç bir durumdur. Burada, 20'den 19 sütun değiştiriliyor; RHS =: = 'hemen hemen tüm tablo. 20'ye bir veya iki sütun eklendiğinde veya 20'nin bir veya iki sütununda değişiklik yapıldığında ': =' nin avantajı daha büyüktür. Bu durumlarda sütunların çoğu yerinde kalır ve ': =' tüm tabloyu kopyalamaktan çok daha hızlıdır. –

+0

Ayrıca, 'set()', v1.8.0'da (henüz CRAN'da değil) doğrudan işlev sağlayan '' = = işlevsellik sağlayan yeni bir işlevdir. 'set()' bir döngü içinde atama yaparken '' = 'den daha hızlı olabilir (daha kolay doğal programlama için). Ana sayfada en son NEWS'de bir örnek var. –

+1

@MatthewDowle - Yorumlarınız için teşekkürler.Haftasonu boyunca, burada verdiğim cevap hakkında kafa yorucu bir duygu yaşadığımı hatırlattılar ve bunu tekrar ziyaret etmeye teşvik ettiler. Açıkçası, nagged hissetmek için iyi bir sebep vardı. Lütfen gözden geçirilmiş cevabıma bir göz atın. Ayrıca ** lütfen yorumlarınızda yer alan önerilerinden herhangi birini, cevaplarımın metnine ekleyebileceksiniz. 'Set()' ye bir bakacağım, ama bunu tartışmaya henüz yeterli hissetmedim. Ve bir kez daha, data.table paketinin sürekli gelişimine yaptığınız tüm işler için teşekkürler! –

6

Bunu yapabilirsin:

library("stringr") 
dt[, -1] <- lapply(dt[, -1], function(x) str_replace(x," ","_")) 
İlgili konular