2014-05-09 19 views
9

Eğer bir fonksiyonun argümanını bir hata veya bir uyarı için deparse etmek isterseniz, argüman bir data.table içinde bir veri dosyasına dönüştürülürse garip bir şey olur. fonksiyonu: data.table her şey iyi çalışır önce onu deparse Eğerdeparse (substitute()) argüman olarak data.table kullanılarak fonksiyon içinde

e <- data.frame(x = 1:10) 
### something strange is happening 
foo <- function(u) { 
    u <- data.table(u) 
    warning(deparse(substitute(u)), " is not a data.table") 
    u 
} 
foo(e) 

## foo(e) 
##  x 
## 1: 1 
## 2: 2 
## 3: 3 
## 4: 4 
## 5: 5 
## 6: 6 
## 7: 7 
## 8: 8 
## 9: 9 
## 10: 10 
## Warning message: 
## In foo(e) : 
## structure(list(x = 1:10), .Names = "x", row.names = c(NA, -10L), class = c("data.table", "data.frame"), .internal.selfref = <pointer: 0x10026568>) is not a data.table 

:

### ok 
foo1 <- function(u) { 
    nu <- deparse(substitute(u)) 
    u <- data.table(u) 
    warning(nu, " is not a data.table") 
    u 
} 
## foo1(e) 
##  x 
## 1: 1 
## 2: 2 
## 3: 3 
## 4: 4 
## 5: 5 
## 6: 6 
## 7: 7 
## 8: 8 
## 9: 9 
## 10: 10 
## Warning message: 
## In foo1(e) : e is not a data.table 

e zaten bir data.table veya eğer hiçbir fark yok arada bulunmamaktadır t. Bu amaçla, deparse'un çok zaman alıcı olduğu için bazı kodları profillendirirken, e oldukça büyük olduğu için bunu buldum.

Burada neler oluyor ve bu işlevleri data.frame ve data.table girişi için nasıl kullanabilirim?

nachti

cevap

10

normal bir değişkenin yerine bir söz nesne ile ilgileniyor zaman substitute farklı davranır olmasıdır. Bir söz nesnesi resmi bir argümandır ve onu oluşturan ifadeyi içeren özel bir yuvaya sahiptir. Başka bir deyişle, bir söz nesnesi, o fonksiyonun argüman listesinin bir parçası olan bir fonksiyondaki bir değişkendir. Bir işlevdeki bir söz nesnesi üzerinde substitute kullandığınızda, bu çağrıdaki ifadeyi bu resmi bağımsız değişkene atanan işleve geri alır. ?substitute Gönderen: o env'deki bir bağlı sembolü değilse, o değişmez:

değişikliği şöyle Çözümleme ağacının her bileşeni inceleyerek gerçekleşir. , bir vaat nesnesi, yani işlevine yönelik resmi bir argümansa veya delayedAssign(), ile açıkça oluşturulmuşsa, sözlüğün ifade yuvası, sembolün yerini alır. Eğer sıradan bir değişken ise, env, .GlobalEnv olmadığı sürece, sembolün değiştirilmediği durumda değeri olarak değiştirilir.

sizin durumda, aslında bir yenisi ile orijinal vaadi değişkenlerin üzerine:

u <- data.table(u) 

bu noktada u bir veri tablosu içeren normal bir değişken haline gelir. Bu noktadan sonra substitute üzerinde substitute, substitute yalnızca deparse yeniden oluşturacak olan R diline işlenen veri tablosunu döndürür, bu nedenle yavaştır.

Bu, ikinci örneğinizin neden çalıştığını da açıklar. substitute, değişken hala bir sözdür (yani u'un üzerine yazmadan önce). Bu aynı zamanda ikinci sorunuzun cevabıdır. Söz verdiğiniz bilgilerin üzerine yazılmadan veya yerine yazılmadan önce ikame edin.

Promise nesneleri R'ın tembel değerlendirme mekanizmasının bir parçasıdır: Daha fazla ayrıntı için

R Dil Tanımı Burada alıntı (vaatler) ait section 2.1.8 görüyoruz. Üç yuva içerir: bir değer, bir ifade ve bir ortam.Bir işlev çağrıldığında, argümanlar eşleştirilir ve daha sonra her bir resmi argümana bir söz verilir. Bu resmi argüman için verilen ifade ve fonksiyonun çağrıldığı çevreye bir işaretçi sözde saklanır.

+0

@nachti, bu sizin sorunuza cevap vermiyor mu? – BrodieG

+0

@ [BrodieG] (http://stackoverflow.com/users/2725969/brodieg): Cevabınız için teşekkürler. Yukarıda yazıldığı gibi: data.frame' ve 'data.table' için bu tür işlevleri nasıl ele alabilirim? Kopyalamalı mıyım (çok yer ihtiyacı var)? Ya da önce her şeyi tahsis et ve sonra üzerine yaz. – nachti

+1

@ nachti, ikincisi, önce deparse. Ayrıca, kopyalardan kaçınmak istiyorsanız, 'data.table' yerine' setDT 'kullanmayı düşünmelisiniz. Eski referans ile bir veri tablosu oluşturur. – BrodieG

0

Muhtemelen ile birlikte is.data.table ile yapabilirsiniz.

> e <- data.frame(x = 1:10) 
> foo <- function(u){ 
     nu <- deparse(substitute(u)) 
     if(!is.data.table(u)){ 
      warning(sprintf('%s is not a data table', nu)) 
      u 
     } else { 
      u 
     } 
    } 
> foo(e) 
    x 
1 1 
2 2 
3 3 
4 4 
5 5 
6 6 
7 7 
8 8 
9 9 
10 10 
Warning message: 
In foo(e) : e is not a data table 
+0

Yanıtlarınız için teşekkürler! @Richard: İyi fikir, ama o zaman hala bir data.table DEĞİL ve '' = = kullanamıyorum. Bir "data.frame" veya bir "data.table" değerini girdi olarak kabul eden, data.table'da birşeyler yapıp onu bir "data.frame" e çeviren bir işlev içinde kullanılmalıdır. biriydi. BTW büyüktür (~ 250 MB) – nachti