2015-01-16 14 views
9

Sử dụng gói data.table R,R data.table ': =' tác phẩm trong cuộc gọi trực tiếp, nhưng cùng chức năng trong một gói không

này hoạt động:

instruction = "a = data.table(name=1:3, value=1:3, blah=1:3); a[,c('value', 'blah'):=NULL]" 
eval(parse(text=instruction)) 
# name 
#1: 1 
#2: 2 
#3: 3 

này hoạt động:

myFunc = function(instruction) { 
eval(parse(text=instruction)) 
} 
myFunc(instruction) 
# name 
#1: 1 
#2: 2 
#3: 3 

Bây giờ, đưa chức năng này vào một gói, tải nó, và cố gắng gọi nó. Điều này không làm việc:

myFuncInPackage(instruction) 
#Error in `:=`(c("value", "blah"), NULL) : 
# Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are defined for use in j, once only and in particular ways. See help(":="). 

Tại sao?


EDIT: @Roland chỉ ra rằng việc thêm dữ liệu .trong trường gói Depends làm cho nó hoạt động. Tuy nhiên, tôi không nghĩ rằng đây là một giải pháp tuyệt vời vì gói không thực sự phụ thuộc vào, yêu cầu hoặc sử dụng data.table. Tôi chỉ muốn có thể sử dụng data.table với gói.

Bên cạnh đó, mọi thứ khác với data.table hoạt động tốt trong hàm, chỉ cần không phải là nhà điều hành :=.

Vì vậy, tôi đoán một câu hỏi tiếp theo có thể là: tôi nên thêm dữ liệu. Có thể cho phụ thuộc của mỗi gói tôi viết, để data.tables làm việc như mong đợi trong các chức năng của gói đó? Điều này có vẻ không đúng ... cách chính xác để tiếp cận điều này là gì?

+2

Bạn đã làm theo lời khuyên trong [Câu hỏi thường gặp 6.9] (http://cran.r-project.org/web/packages/data.table/vignettes/datatable-faq.pdf) chưa? Ngoài ra, việc sử dụng 'eval (parse())' không được khuyến khích. – Roland

+0

@Roland Thêm data.table vào Depends giải quyết nó ... nhưng dẫn đến một vấn đề: gói của tôi không thực sự phụ thuộc vào data.table; trên thực tế, nó hoàn toàn không liên quan. Như trong ví dụ này, nó chỉ có một hàm, 'myFunc' - không có dữ liệu. Nhưng nó không thể được sử dụng với data.table mà không cần thêm nó vào Depends ... – nsheff

+0

@Roland, tôi biết, 'eval (parse())' không được khuyến khích, và đây là một ví dụ vô nghĩa, nhưng câu hỏi vẫn đứng vững. ..trong một số trường hợp, tôi không thể đi lại. – nsheff

Trả lời

0

Cuối cùng tôi đã tìm ra câu trả lời cho câu hỏi này (sau vài năm). Tất cả các ý kiến ​​và câu trả lời đề nghị thêm data.table-Depends hoặc Imports, nhưng điều này là không chính xác; gói không phụ thuộc vào data.table và đó có thể là bất kỳ gói giả thuyết, không chỉ data.table, có nghĩa là đưa đến kết luận hợp lý, đề nghị sẽ đòi hỏi thêm tất cả các gói có thể Depends - kể từ khi sự phụ thuộc được cung cấp bởi người sử dụng cung cấp instruction, không phải bởi chức năng được cung cấp bởi gói. Thay vào đó, về cơ bản, đó là vì gọi tới eval được thực hiện trong vùng tên của gói và điều này không bao gồm các chức năng được cung cấp bởi các gói khác. Tôi cuối cùng giải quyết điều này bằng cách xác định môi trường toàn cầu trong eval gọi:

myFunc = function(instruction) { 
eval(parse(text=instruction), envir=globalenv()) 
} 

Tại sao các công trình này

Điều này làm cho eval chức năng để được thực hiện trong môi trường đó sẽ bao gồm các gói cần thiết trong việc tìm kiếm con đường.

Trong trường hợp data.table nó đặc biệt khó khăn để gỡ lỗi vì sự phức tạp của hàm quá tải. Trong trường hợp này, thủ phạm không phải là thực sự là := chức năng, nhưng [ chức năng. Các lỗi := là một cá trích đỏ.Tại thời điểm viết bài, các := chức năng trong data.table được định nghĩa như thế này:

https://github.com/Rdatatable/data.table/blob/348c0c7fdb4987aa6da99fc989431d8837877ce4/R/data.table.R#L2561

":=" <- function(...) stop('Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are defined for use in j, once only and in particular ways. See help(":=").')

Vậy là xong. Điều đó có nghĩa là: mọi cuộc gọi đến := là một chức năng bị dừng với thông báo lỗi, vì đây không phải là cách tác giả dự định sử dụng :=. Thay vào đó, := thực sự chỉ là từ khóa được giải thích bởi hàm [ trong data.table.

Nhưng những gì xảy ra ở đây: nếu chức năng [ không được ánh xạ một cách chính xác lên phiên bản theo quy định của data.table, và thay vào đó là ánh xạ tới các cơ sở [, sau đó chúng tôi có một vấn đề - vì nó không thể xử lý := và do đó nó được coi là một hàm và kích hoạt thông báo lỗi. Vì vậy, chức năng thủ phạm là [.data.table - toán tử khung quá tải.

gì đang xảy ra là trong gói mới của tôi (chứa myFuncInPackage), khi nó đi để đánh giá mã, nó giải quyết các [ chức năng với chức năng cơ sở [ thay vì để data.table 's [ chức năng. Nó cố gắng để đánh giá := là một hàm không được tiêu thụ bởi [ vì nó không phải là đúng [, vì vậy := được chuyển thành hàm thay vì giá trị thành data.table vì không có vùng tên (data.table) hoặc là thấp hơn trong hệ thống phân cấp search(). trong bối cảnh này, := không hiểu và vì vậy nó được đánh giá là một chức năng, do đó kích hoạt các thông báo lỗi trong mã data.table trên.

Khi bạn chỉ định eval xảy ra trong toàn cầu môi trường, nó giải quyết một cách chính xác hàm [ đến [.data.table:= được diễn giải chính xác

Ngẫu nhiên, bạn cũng có thể sử dụng điều này nếu bạn đang đi qua không phải là một chuỗi ký tự nhưng một khối mã (tốt hơn) để eval() bên trong một gói:

eval(substitute(instruction), envir=globalenv())

Ở đây, substitute ngăn ngừa sự instruction từ việc phân tích cú pháp (không chính xác) trong vùng tên gói tại giai đoạn đánh giá-đối số, để nó làm cho nó trở lại nguyên vẹn với globalenv, nơi nó có thể được đánh giá đúng với các hàm được yêu cầu tại chỗ.

5

Tôi gặp sự cố tương tự và tôi đã giải quyết vấn đề thêm data.table đến ImportsDepends:. Phiên bản data.table của tôi là 1.9.6

+0

Bạn có thể đưa ra một ví dụ không? - - Tôi có tập lệnh có chức năng sử dụng 'data.table'. Tôi nhận được lỗi ở đây. Tôi bao gồm 'thư viện (data.table)' trong kịch bản và/hoặc trong chính hàm đó. - - Bạn cũng có thể đưa ra một ví dụ về cách bạn áp dụng 'Imports' và' Depends: 'ở đây để giải quyết vấn đề. Data.table của tôi là 1.10.4. –

+2

Nó làm việc cho tôi trong bối cảnh gói R - không phải kịch bản thô. Nhưng trả lời cho câu hỏi của bạn - bạn có thể áp dụng nó trong tệp 'DESCRIPTION': ' Nhập: data.table (> = 1.9.6) Phụ thuộc: data.table (> = 1.9.6) ', ví dụ: https: // pastebin.com/uy10Devh – Taz

+0

Bạn có thể ngăn các gói được tải bởi các thông số kỹ thuật như vậy không? Etc 'import data.table' nhưng ngăn chặn' reshape2' được tải dưới dạng gói riêng. –

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