Làm cách nào để tải một đối tượng vào một tên biến mà tôi chỉ định từ tệp dữ liệu R?


97

Khi bạn lưu một biến trong tệp dữ liệu R bằng cách sử dụng save, nó sẽ được lưu dưới bất kỳ tên nào mà nó có trong phiên đã lưu nó. Sau đó, khi tôi tải nó từ một phiên khác, nó sẽ được tải với cùng một tên, mà kịch bản tải không thể biết được. Tên này có thể ghi đè biến hiện có cùng tên trong phiên tải. Có cách nào để tải một đối tượng từ tệp dữ liệu vào một tên biến được chỉ định một cách an toàn mà không có nguy cơ làm tắc các biến hiện có không?

Thí dụ:

Đang lưu phiên:

x = 5
save(x, file="x.Rda")

Đang tải phiên:

x = 7
load("x.Rda")
print(x) # This will print 5. Oops.

Cách tôi muốn nó hoạt động:

x = 7
y = load_object_from_file("x.Rda")
print(x) # should print 7
print(y) # should print 5

Câu trả lời:


93

Nếu bạn chỉ lưu một đối tượng, không sử dụng .Rdatatệp, hãy sử dụng .RDStệp:

x <- 5
saveRDS(x, "x.rds")
y <- readRDS("x.rds")
all.equal(x, y)

Cập nhật để phản ánh rằng trong 2.13, chúng không còn thử nghiệm nữa.
hadley

Điều đó có nghĩa là chúng được hỗ trợ đầy đủ, giống như tệp .Rdata?
Ryan C. Thompson

Vì đây không còn là thử nghiệm nữa, tôi đánh dấu đây là câu trả lời được chấp nhận. Đây là những gì tôi đã được sử dụng.
Ryan C. Thompson

Thực hiện saveRDSreadRDStương ứng, lưu và khôi phục tất cả các thuộc tính của đối tượng, bao gồm cả những thuộc tính được tạo bởi một ứng dụng (thông qua attr)? Tôi đã cố gắng sử dụng cách tiếp cận này thay vì saveloadcố gắng tìm ra giải pháp cho vấn đề của mình. Dù sao đi nữa, có vẻ như không phải vậy, trừ khi tôi đang làm sai điều gì đó: stackoverflow.com/questions/23701195/… .
Aleksandr Blekh

37

Tôi sử dụng như sau:

loadRData <- function(fileName){
#loads an RData file, and returns it
    load(fileName)
    get(ls()[ls() != "fileName"])
}
d <- loadRData("~/blah/ricardo.RData")

1
Đây là một chức năng nhỏ tuyệt vời. Đã gặp vấn đề với cố gắng để điều tải trong (muốn didnt để chỉ cần đặt chúng trong môi trường toàn cầu như tôi biết rằng đang xảy ra vấn đề.
Trevor Nederlof

4
Một cái gì đó như thế này thuộc về cơ sở R
Repmat

1
CHÚA ƠI. Điều này thật tuyệt. Chỉ cần những gì tôi cần! #loveit
Sander W. van der Laan

Bạn có thể vui lòng mở rộng logic của câu lệnh GET không? Tại sao không đối sánh với FILENAME thay vì loại trừ?
nnachefski 21/1217

35

Bạn có thể tạo một môi trường mới, tải tệp .rda vào môi trường đó và truy xuất đối tượng từ đó. Tuy nhiên, điều này áp đặt một số hạn chế: bạn biết tên ban đầu cho đối tượng của mình là gì hoặc chỉ có một đối tượng được lưu trong tệp.

Hàm này trả về một đối tượng được tải từ tệp .rda được cung cấp. Nếu có nhiều hơn một đối tượng trong tệp, một đối tượng tùy ý sẽ được trả về.

load_obj <- function(f)
{
    env <- new.env()
    nm <- load(f, env)[1]
    env[[nm]]
}

3
new.envthực sự cần thiết? Không phải chính lệnh gọi hàm cung cấp một môi trường tạm thời?
Ryan C. Thompson

Bạn có thể trả về toàn bộ môi trường (return (env) hoặc trả về (môi trường ()) khi bạn sửa đổi chức năng theo gợi ý @Ryan).
Wojciech Sobala

2
Nếu bạn sử dụng môi trường hàm, nó sẽ chứa f và có cha. Có lẽ không phải những gì bạn muốn
hadley

27

Bạn cũng có thể thử một cái gì đó như:

# Load the data, and store the name of the loaded object in x
x = load('data.Rsave')
# Get the object by its name
y = get(x)
# Remove the old object since you've stored it in y 
rm(x)

4
Vấn đề là tránh làm tắc nghẽn giá trị của x khi tải.
Ryan C. Thompson

2

Trong trường hợp bất kỳ ai đang tìm cách thực hiện việc này bằng tệp nguồn thuần túy, thay vì tệp Rdata / RDS / Rda đã lưu, thì giải pháp rất giống với giải pháp được cung cấp bởi @Hong Ooi

load_obj <- function(fileName) {

  local_env = new.env()
  source(file = fileName, local = local_env)

  return(local_env[[names(local_env)[1]]])

}

my_loaded_obj = load_obj(fileName = "TestSourceFile.R")

my_loaded_obj(7)

Bản in:

[1] "Giá trị của arg là 7"

Và trong tệp nguồn riêng TestSourceFile.R

myTestFunction = function(arg) {
  print(paste0("Value of arg is ", arg))
}

Một lần nữa, giải pháp này chỉ hoạt động nếu có chính xác một tệp, nếu có nhiều tệp hơn, thì nó sẽ chỉ trả về một trong số chúng (có thể là tệp đầu tiên, nhưng điều đó không được đảm bảo).


1

Tôi đang mở rộng câu trả lời từ @ricardo để cho phép lựa chọn biến cụ thể nếu .Rdatatệp chứa nhiều biến (vì tín dụng của tôi thấp để chỉnh sửa câu trả lời). Nó thêm một số dòng để đọc đầu vào của người dùng sau khi liệt kê các biến có trong .Rdatatệp.

loadRData <- function(fileName) {
  #loads an RData file, and returns it
  load(fileName)
  print(ls())
  n <- readline(prompt="Which variable to load? \n")
  get(ls()[as.integer(n)])
}

select_var <- loadRData('Multiple_variables.Rdata')


1

Tệp Rdata với một đối tượng

assign('newname', get(load('~/oldname.Rdata')))

1
Điều này sẽ không tải đối tượng vào tên cũ, và sau đó cũng gán nó cho tên mới? Điều đó sẽ không hữu ích nếu tôi lo lắng về khả năng ghi đè một biến hiện có.
Ryan C. Thompson
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.