2010-09-22 11 views
6

Próbowałem użyć acast z reshape2 w ramach funkcji napisanej samodzielnie, ale miałem problem z tym, że acast nie znalazł danych, które do niego wysłałem.Jak używać acast (reshape2) w funkcji w R?

Oto moje dane:

library("reshape2") 
x <- data.frame(1:3, rnorm(3), rnorm(3), rnorm(3))  
colnames(x) <- c("id", "var1", "var2", "var3") 
y <-melt(x, id = "id", measure = c("var1", "var2", "var3")) 

y wówczas wygląda następująco:

id variable  value 
1 1  var1 0.1560812 
2 2  var1 1.0343844 
3 3  var1 -1.4157728 
4 1  var2 0.8808935 
5 2  var2 0.1719239 
6 3  var2 0.6723758 
7 1  var3 -0.7589631 
8 2  var3 1.1325995 
9 3  var3 -1.5744876 

teraz mogę rzucać go z powrotem poprzez acast:

> acast(y,y[,1] ~ y[,2]) 
     var1  var2  var3 
1 0.1560812 0.8808935 -0.7589631 
2 1.0343844 0.1719239 1.1325995 
3 -1.4157728 0.6723758 -1.5744876 

Jednak podczas pisania małe opakowanie dla acast, które powinno zrobić to samo, mam głupie komunikaty o błędach:

wrap.acast <- function(dat, v1 = 1, v2 = 2) { 
    out <- acast(dat, dat[,v1] ~ dat[,v2]) 
    return(out) 
} 

wrap.acast(y) 

Error in eval(expr, envir, enclos) : object 'dat' not found 

Problem jest oczywiście związany z czymś takim jak środowiska i zmienne globalne/lokalne. Ponieważ nie podaje innych komunikatów o błędach po stwierdzeniu, że dat w środowisku globalnym (tj. v1 i v2 nie zostaną znalezione, dopóki nie są globalne).

Chciałbym użyć resahpe (szczególnie acast) w funkcji bez konieczności zadeklarowania zmiennych poza funkcją. Jaka jest sztuczka?

Dzięki.

+0

Jest to problem, który występuje częściej w ostatnim czasie. Początkowo odkryłem, że jest to problem z metodami S4, ale najwyraźniej może również wystąpić z innymi funkcjami. Jest to podobno błąd w R, zobacz także odpowiedzi na to pytanie: http://stackoverflow.com/questions/3574858/values-not-being-copied-to-the-next-local-environment/ –

+0

Dzięki Joris. Ale teraz mam wrażenie, że nie ma łatwego rozwiązania mojego problemu. niezbyt miły ... – Henrik

+0

Właśnie się dowiedziałem, że jest jeden. To kwestia prawidłowego typowania. –

Odpowiedz

5

Zamiast specyfikacji formuły, użyj specyfikacji znaków:

acast(y, list(names(y)[1], names(y)[2])) 
+0

To jeszcze prostsze. Wielkie dzięki. I jeszcze więcej dzięki za dostarczenie reshape2 i wszystkich twoich świetnych pakietów! – Henrik

2

Korekta: problem nie polega na tym, że nie znajduje dat, ale że nie znajduje dat [, v1] i dat [, v2] w podanej formule. Acast przyjmuje argument formuły typu, który jest oceniany w tymczasowym środowisku utworzonym wokół ramki danych. W tym środowisku nie znajduje obiektu "dat", gdy funkcja jest zawijana w innym.

Nie podążam całkowicie za tym, jak to działa w skali globalnej, a nie po zapakowaniu, ale jeśli karmisz acast formułę, to działa również w ramach funkcji.

wrap.acast <- function(dat, v1 = 1, v2 = 2) { 
    x1 <- names(dat)[v1] 
    x2 <- names(dat)[v2] 
    form <- as.formula(paste(x1,"~",x2)) 
    out <- acast(dat,form) 
    return(out) 
} 

wykorzystujące dane zabawki:

> wrap.acast(y) 
     var1  var2  var3 
1 0.04095337 0.4044572 -0.4532233 
2 1.23905358 1.2493187 0.7083557 
3 0.72798307 0.7868746 1.7144811 
+0

Tego właśnie chciałem. Wielkie dzięki. – Henrik

-2

znalazłem dość nieeleganckiego sposób, aby rozwiązać ten problem przy użyciu Super przypisania (<<-).
Zmiana funkcji na następujące powoduje wykonanie zadania. Jest jednak dość brzydka, ponieważ tworzy zmienne globalne, które pozostają.

wrap.acast <- function(dat, v1 = 1, v2 = 2) { 
    dat <<- dat 
    v1 <<- v1 
    v2 <<- v2 
    out <- acast(dat, dat[,v1] ~ dat[,v2]) 
    return(out) 
} 

Nadal bardzo interesują mnie inne (mniej zatkania) rozwiązania.

przed uruchomieniem funkcji:

> ls() 
[1] "wrap.acast" "x"   "y"  

po uruchomieniu funkcji:

> ls() 
[1] "dat"  "v1"   "v2"   "wrap.acast" "x"   
[6] "y" 
+0

Jak sam zauważyłeś, należy unikać używania super zadań, chyba że naprawdę chcesz utworzyć zmienną globalną. A nawet wtedy możesz przemyśleć problem ... –

4

jeden problem jest to, że nadużywasz notacji formuły w R. Nie powinieneś robić takich rzeczy jak

> acast(y, y[,1] ~ y[,2]) 
     var1  var2   var3 
1 2.1726117 0.6107264 0.291446236 
2 0.4755095 -0.9340976 -0.443291873 
3 -0.7099464 -1.2536334 0.001105352 

ponieważ bity "y" są zbędne, jeśli obiekt danych jest dostarczany. Jeśli odnoszą się do zmiennych y wg nazwy bezpośrednio w formule, wszystko działa ładnie

> acast(y, id ~ variable) 
     var1  var2   var3 
1 2.1726117 0.6107264 0.291446236 
2 0.4755095 -0.9340976 -0.443291873 
3 -0.7099464 -1.2536334 0.001105352 

a kod jest bardziej czytelny w tej drugiej wersji.

Aby zrobić to, co chcesz, za pomocą wrappera acast trzeba będzie wygenerować poprawną formułę za pomocą names, jak wskazuje Joris, a rozwiązanie Hadleya jest znacznie prostsze. Więc naprawdę chodzi mi o to, by uważać na to, w jaki sposób korzystasz ze specyfikacji formuły w R. Na dłuższą metę uratujesz sobie wiele kłopotów (ale nie specjalnie z tym konkretnym problemem), jeśli używasz formuł poprawnie.

Powiązane problemy