2012-01-02 32 views
40

Tôi có một tập tin Rdata chứa các đối tượng khác nhau:Nhận đối tượng cụ thể từ các rdata nộp

New.Rdata 
    |_ Object 1 (e.g. data.frame) 
    |_ Object 2 (e.g. matrix) 
    |_... 
    |_ Object n 

Dĩ nhiên tôi có thể tải các khung dữ liệu với load('New.Rdata') Tuy nhiên, có một cách thông minh để tải chỉ có một đối tượng cụ thể ra của tệp này và loại bỏ các tệp khác?

+1

Trong nhận xét, @DWin nói không. http://stackoverflow.com/questions/6550510/examining-contents-of-rdata-file-by-attaching-into-a-new-environment-possible –

+1

Nhưng trong mọi vấn đề-R tôi trì hoãn Simon. –

Trả lời

61

. Tệp dữ liệu không có chỉ mục (nội dung được đăng theo thứ tự là một danh sách cặp đôi lớn). Bạn có thể hack một cách để đi qua các cặp đôi và chỉ gán mục bạn thích, nhưng nó không phải dễ dàng vì bạn không thể làm điều đó ở cấp R.

Tuy nhiên, bạn chỉ có thể chuyển đổi tệp .RData thành cơ sở dữ liệu tải lười, nối tiếp từng mục nhập riêng biệt và tạo chỉ mục. Điều tốt đẹp là tải sẽ theo yêu cầu:

# convert .RData -> .rdb/.rdx 
e = local({load("New.RData"); environment()}) 
tools:::makeLazyLoadDB(e, "New") 

Tải DB sau đó chỉ tải chỉ mục chứ không tải nội dung. Nội dung được nạp khi chúng được sử dụng:

lazyLoad("New") 
ls() 
x # if you had x in the New.RData it will be fetched now from New.rdb 

Cũng giống như với load() bạn có thể chỉ ra một môi trường để nạp vào, do đó bạn không cần phải làm ô nhiễm không gian làm việc toàn cầu, vv

+1

Nhưng việc tra cứu vẫn sẽ yêu cầu truy cập nối tiếp thông qua "New.RData" để nhận "x", phải không? Vì vậy, nếu "x" là ở phần cuối của "New.RData", có thể không có tiết kiệm thời gian? Câu hỏi 2: sẽ không có bộ nhớ được đưa lên với các đối tượng khác gặp phải khi quá trình unserialization hoạt động theo cách của mình thông qua "New.RData"? –

+1

Không, tra cứu chỉ tìm kiếm vào 'New.rdb' ở đầu' x' và chỉ tải 'x'. –

+8

Khả năng của các chức năng này trở nên ít nội bộ hơn là gì? – hadley

10

Bạn có thể sử dụng attach thay hơn load sẽ đính kèm đối tượng dữ liệu vào đường dẫn tìm kiếm, sau đó bạn có thể sao chép một đối tượng mà bạn quan tâm và tách đối tượng .Rdata.

Điều này vẫn tải mọi thứ, nhưng đơn giản hơn khi tải mọi thứ vào không gian làm việc toàn cầu (có thể ghi đè lên những thứ bạn không muốn ghi đè) rồi loại bỏ mọi thứ bạn không muốn.

+3

Câu trả lời này là tốt nhưng sẽ hoàn chỉnh hơn với một ví dụ, vì việc tách đối tượng .RData khỏi đường dẫn tìm kiếm không trực quan. Ví dụ để lấy 'someObj' từ' someFile.RData': 'attach ('someFile.RData'); someObj <- someObj; tách ('file: someFile.RData') ' – C8H10N4O2

+0

@ C8H10N4O2, ví dụ của bạn là tốt (và rất rõ ràng). Nhưng nếu bạn đính kèm vào vị trí mặc định (2) và không đính kèm bất cứ điều gì khác trước khi gọi tách, sau đó mặc định làm việc và bạn chỉ có thể gọi 'tách()' mà không có bất kỳ đối số và nó sẽ tách các tập tin. Điều này nhanh hơn và đơn giản hơn; cách tiếp cận của bạn an toàn hơn. –

4

Câu trả lời của Simon Urbanek rất, rất hay. Một nhược điểm là nó dường như không có tác dụng nếu một đối tượng được cứu rỗi là quá lớn:

tools:::makeLazyLoadDB(
    local({ 
    x <- 1:1e+09 
    cat("size:", object.size(x) ,"\n") 
    environment() 
    }), "lazytest") 
size: 4e+09 
Error: serialization is too large to store in a raw vector 

Tôi đoán rằng điều này là do một hạn chế của việc thực hiện hiện tại của R (Tôi có 2.15. 2) thay vì hết bộ nhớ vật lý và trao đổi. Tuy nhiên, gói saves có thể là một thay thế cho một số ứng dụng.

+1

Đây là một nhận xét mở rộng hơn là một câu trả lời. – C8H10N4O2

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