使用R中的活动绑定读取/写入文件

时间:2016-01-18 20:28:45

标签: r

我正在尝试在R SAS样式库中实现,您可以在其中定义与目录对应的库对象,然后通过为库成员分配文件到该磁盘。

以下代码适用于已存在的文件。因此,如果您已经有一个包含文件的目录,您可以通过myLib$file阅读它们并使用myLib$file <- value写信给他们。我无法弄清楚做的是通过myLib$newfilename <- value写一个新文件。

任何人都知道如何实现这个目标?

library(plyr)
# What this does:
# A function which creates an active binding to a given name, and using
# the given directory path.  Upon access, the binding creates an environment
# with active bindings for each file in that directory which will use readRDS
# on access and saveRDS on change.

# What this doesn't do:
# Can't use this to write to a file that doesn't yet exist.  If the directory
# has blah1.rdata and blah2.rdata, you can do myLib$blah3.rdata <- 1.  Instead
# of writing to disk, this will simply assign the value of 1 into an the env
# returned by the outer active binding.

# What tried and failed to do:
# I tried to set this up so that the outer active binding catches where the
# user tries 
lib <- function(libname,path){
  # Assign the name libname as an active binding in the global environment
  makeActiveBinding(
    libname,
    function(value){
      if(missing(value)){
        # If user is reading from binding, find all the files in the given
        # path that use the .rdata extension, create an environment, and
        # populate it with active bindings for each .rdata file which will
        # read/write using readRDS/saveRDS.
        regex <- "^.*\\.(rdata)$"
        files <- list.files(
          path=path,
          pattern = regex,
          ignore.case=TRUE
        )
        myEnv <- new.env()
        myEnv$path <- path
        l_ply(
          seq_along(files),
          function(i){
          makeActiveBinding(
            files[i],
            function(value){
              if(missing(value)){
                readRDS(paste0(path,"/",files[i]))
              }else{
                saveRDS(value,paste0(path,"/",files[i]))
              }
            },
            myEnv
          )
        })
        return(myEnv)
      }else{
        # If the user is writing to a binding, this should be set to
        # figure out what name the user is writing to, then do saveRDS
        # to the given library's path using that name as a filename.
        # 
        # Can't figure out how to make it work as I can't capture the
        # name being assigned to from the call...
        #
        # Note that this code only triggers and is necessary in the
        # case where the user is writing to a name that does not
        # correspond to an already existing file in the given directory
        #invisible(NULL)
      }
    },
    .GlobalEnv
  )
}

# Directory to use
myDirectory <- "./"

# Pre-populate a couple files
saveRDS(mtcars,paste0(myDirectory,"/","myCars.rdata"))
saveRDS(iris,paste0(myDirectory,"/","myPlants.rdata"))

# Initialize binding
lib("myLib",path = myDirectory)

# print object from disk
print(head(myLib$myCars.rdata))

# write over object using cars instead of mtcars
myLib$myCars.rdata <- cars

# This works!  It prints cars now instead of mtcars even using readRDS
print(head(readRDS(paste0(myDirectory,"/","myCars.rdata"))))
print(head(myLib$myCars.rdata))

# Wish I could write to a file that doesn't yet exist, but don't
# know how to make it work
myLib$somethingelse.rdata <- 10

0 个答案:

没有答案