2010-09-22 30 views
6

Tôi đã cố gắng sử dụng acast từ reshape2 trong chức năng tự viết, nhưng có vấn đề là acast không tìm thấy dữ liệu tôi gửi cho nó.Làm thế nào để sử dụng acast (reshape2) trong một hàm trong R?

Đây là dữ liệu của tôi:

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 sau đó trông như thế này:

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 

bây giờ tôi có thể bỏ nó trở lại qua 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 

Tuy nhiên, khi viết một nhỏ wrapper cho acast mà nên làm như vậy, tôi nhận được một stupid thông báo lỗi:

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 

Vấn đề rõ ràng là có liên quan đến môi trường và biến toàn cầu/cục bộ. Vì nó cung cấp các thông báo lỗi khác sau khi khai báo dat trong môi trường toàn cầu (tức là, v1v2 không được tìm thấy miễn là chúng không phải là toàn cầu).

Tôi muốn sử dụng resahpe (đặc biệt là acast) trong một hàm mà không cần phải khai báo các biến bên ngoài hàm. Bí quyết là gì?

Cảm ơn.

+0

Đây là vấn đề xảy ra thường xuyên hơn gần đây. Ban đầu tôi thấy nó là một vấn đề với phương pháp S4, nhưng dường như nó có thể xảy ra với các chức năng khác nữa. Đây được cho là lỗi trong R, xem thêm câu trả lời cho câu hỏi này: http://stackoverflow.com/questions/3574858/values-not-being-copied-to-the-next-local-environment/ –

+0

Cảm ơn Joris. Nhưng bây giờ tôi có ấn tượng rằng không có giải pháp dễ dàng cho vấn đề của tôi. không quá đẹp ... – Henrik

+0

Chỉ cần phát hiện ra có một thực sự. Đó là vấn đề chính xác của việc in ấn. –

Trả lời

5

Thay vì sử dụng các đặc điểm kỹ thuật công thức, sử dụng đặc tả nhân vật:

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

Điều đó thậm chí còn đơn giản hơn. Cảm ơn nhiều. Và thậm chí cảm ơn bạn nhiều hơn vì đã cung cấp reshape2 và tất cả các gói tuyệt vời của bạn! – Henrik

2

Hiệu chỉnh: vấn đề không phải là nó không tìm thấy dat, nhưng nó không tìm thấy dat [, v1] và dat [, v2] trong công thức được chỉ định. Acast lấy một đối số của công thức kiểu, và cái đó được đánh giá trong môi trường tạm thời được tạo xung quanh khung dữ liệu của bạn. Trong môi trường đó, nó không tìm thấy đối tượng "dat" khi hàm được bọc trong một đối tượng khác.

Tôi không hoàn toàn theo dõi cách thức hoạt động của tính năng này trong toàn cầu và không được bao bọc, nhưng nếu bạn nạp một công thức, nó cũng hoạt động trong một hàm.

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) 
} 

sử dụng dữ liệu đồ chơi của bạn:

> 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

Đây là những gì tôi muốn. Cảm ơn rất nhiều. – Henrik

-2

Tôi tìm thấy một cách khá thanh nha để giải quyết vấn đề sử dụng bài tập siêu (<<-).
Thay đổi chức năng thành công việc sau. Tuy nhiên, nó là khá xấu vì nó tạo ra các biến toàn cầu mà vẫn còn.

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

Tôi vẫn rất quan tâm đến các giải pháp khác (ít bị tắc nghẽn).

trước khi chạy chức năng:

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

sau khi chạy chức năng:

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

Khi bạn nhận thấy chính mình, việc sử dụng các nhiệm vụ siêu nên tránh mọi lúc, trừ khi bạn thực sự muốn tạo ra một biến toàn cục. Và thậm chí sau đó bạn có thể muốn suy nghĩ lại vấn đề ... –

4

Một vấn đề là bạn đang lạm dụng ký hiệu công thức trong R. Bạn không nên làm những việc như

> 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 

vì các bit 'y' thừa nếu đối tượng dữ liệu được cung cấp. Nếu bạn đề cập đến các biến y theo tên trực tiếp trong công thức, mọi thứ hoạt động độc đáo

> 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 

và mã này dễ đọc hơn trong phiên bản thứ hai này.

Để thực hiện những gì bạn muốn bằng cách sử dụng trình bao bọc acast sẽ liên quan đến việc tạo công thức chính xác bằng cách sử dụng names, như Joris chỉ ra và giải pháp của Hadley đơn giản hơn rất nhiều. Vì vậy, điểm của tôi thực sự là để xem ra với cách bạn sử dụng đặc tả công thức trong R. Bạn sẽ tiết kiệm cho mình rất nhiều rắc rối trong thời gian dài (mặc dù không cụ thể với vấn đề cụ thể này) nếu bạn sử dụng công thức đúng cách.

Các vấn đề liên quan