2014-08-29 29 views
12

Trong Perl (và có lẽ là các langauges khác), bạn có thể "buộc" một biến để thay thế hành vi được tích hợp sẵn với hành vi do người dùng xác định. Ví dụ, một bảng băm có thể được gắn với tùy chỉnh "lấy" và "lấy" các chương trình con, ví dụ, truy vấn BerkeleyDB để dữ liệu liên tục và không bị giới hạn bởi RAM, nhưng vẫn trông và hoạt động như băm thông thường cho Perl.Bạn có thể "buộc" hoặc cung cấp triển khai thay thế, của một data.frame trong R không?

Có điều gì tương tự với R? Đặc biệt, tôi nghĩ, vì một data.frame trông giống như một bảng trong một db quan hệ, nếu một data.frame được gắn với một cái gì đó như SQLite, nó sẽ cho phép R xử lý các khung dữ liệu rất lớn (tôi đã nhồi 100GB + vào SQLite) mà không có bất kỳ thay đổi mã nào.

+2

Hãy thử gói 'sqldf' cho vấn đề thực tế của bạn, nhưng tôi nghĩ rằng những gì bạn đang đề xuất là cơ chế lớp S3. – James

+1

kiểm tra các gói 'ff' và' ffbase', chúng được xây dựng trên nguyên tắc chính xác đó. –

+4

'data.table' và' dplyr' mới 'tbl_ *' – hrbrmstr

Trả lời

2

Khi nhận xét chỉ ra, một số gói đã được xây dựng dựa trên ý tưởng này (hoặc tương tự).

data.tabledplyr đặc biệt tốt trong việc xử lý dữ liệu rất lớn và truy vấn chúng. Nếu data.frame thực sự là> 100GB, tôi muốn khuyên bạn nên data.table mà dường như tốt hơn dplyr trong giới hạn nrow-> Inf. Cả hai đều có hỗ trợ tuyệt vời trên stackoverflow nếu bạn cần nó.

Tuy nhiên, để thực sự trả lời câu hỏi của bạn (và hữu ích cho độc giả tương lai của câu hỏi này): có, bạn có thể tính thêm một hàm với R để cung cấp hành vi thay thế. Nó thực sự rất dễ dàng với hệ thống gửi S3. Tôi khuyên bạn nên this ressource để tìm hiểu thêm.

Tôi sẽ cung cấp cho bạn phiên bản ngưng: Nếu bạn có đối tượng lớp "myclass", bạn có thể viết hàm f.myclass để làm những gì bạn muốn.

Sau đó, bạn xác định một hàm tổng quát f:

f <- function(obj, ...) UseMethod("f", obj, ...) 

Khi bạn gọi f(obj), chức năng mà UseMethod sẽ gọi phụ thuộc vào lớp của obj.

Nếu obj thuộc lớp "myclass", thì f.myclass sẽ được gọi trên obj.

Nếu chức năng bạn muốn xác định lại đã tồn tại, hãy nói plot, thì bạn có thể chỉ cần xác định plot.myclass sẽ được sử dụng khi bạn gọi plot trên đối tượng "myclass". Chức năng chung đã tồn tại, không cần phải xác định lại nó.

Để thay đổi lớp của đối tượng (hoặc thêm lớp mới vào các lớp hiện có, thường không phá vỡ hành vi bạn không muốn thay đổi), bạn có thể sử dụng class<-.

Đây là ví dụ ngớ ngẩn.

> print.myclass <- function(x) { 
    print("Hello!")} 

> df <- data.frame(a=1:3) 
> class(df) 
[1] "data.frame" 
> df #equivalent to print(df) 
    a 
1 1 
2 2 
3 3 

> class(df) <- append(class(df), "myclass") 
> class(df) 
[1] "data.frame" "myclass" 

> class(df) <- "myclass" 
> class(df) 
[1] "myclass" 
> df 
[1] "Hello!" 
> str(df) # checking the structure of df: the data is still there of course 
List of 1 
$ a: int [1:3] 1 2 3 
- attr(*, "row.names")= int [1:3] 1 2 3 
- attr(*, "class")= chr "myclass" 

Có một số sự tinh tế, như chức năng được gọi nếu có nhiều lớp, theo thứ tự nào, v.v .. Tôi giới thiệu cho bạn giải thích kỹ lưỡng về hệ thống S3.

Đó là cách bạn sẽ xác định lại hành vi của các hàm. Viết lại chúng thành f.myclass và sau đó tạo đối tượng của lớp "myclass".

Hoặc, bạn có thể xác định lại f.targetclass.Ví dụ, một lần nữa với printdata.frame:

> print.data.frame <- function(x) { 
     print(paste("data.frame with columns:", paste(names(x), collapse = ", ")))} # less silly example! 
> df <- data.frame(a=1:3, b=4:6) 
> df 
[1] "data.frame with columns: a, b" 
Các vấn đề liên quan