Saving object attributes using a function - r

I'm trying to modify the save() function so that the script from which the object originated is stored as an attribute of the object.
s = function(object, filepath, original.script.name){
#modified save() function
#stores the name of the script from which the object originates as an attribute, then saves as normal
attr(object, "original.script") = original.script.name
save(object, file = filepath)
}
Sample:
testob = 1:10
testob
# [1] 1 2 3 4 5 6 7 8 9 10
s(testob, filepath = "rotation1scripts_v4/saved.objects/testob", "this.is.the.name")
load(file = "rotation1scripts_v4/saved.objects/testob")
testob
# [1] 1 2 3 4 5 6 7 8 9 10
attributes(testob)
# NULL
Investigating further, it seems that the object is not being loaded into the environment:
testob2 = 1:5
testob2
# [1] 1 2 3 4 5
s(testob2, "rotation1scripts_v4/saved.objects/testob2", "this.is.the.name")
rm(testob2)
load(file = "rotation1scripts_v4/saved.objects/testob2")
testob2
# Error: object 'testob2' not found
Why isn't it working?

You need to be careful with save(). It saves variables with the same name that's passed to save(). So When you call save(object, ...), it's saving the variable as "object" and not "testob" which you seem to be expecting. You can do some non-standard environment shuffling to make this work though. Try
s <- function(object, filepath, original.script.name){
objectname <- deparse(substitute(object))
attr(object, "original.script") = original.script.name
save_envir <- new.env()
save_envir[[objectname]] <- object
save(list=objectname, file = filepath, envir=save_envir)
}
We use deparse(substitute()) to the get name of the variable passed to the function. Then we create a new environment where we can create the object with the same name. This way we can use that name when actually saving the object.
This appears to work if we test with
testob <- 1:10
s(testob, filepath = "test.rdata", "this.is.the.name")
rm(testob)
load(file = "test.rdata")
testob
# [1] 1 2 3 4 5 6 7 8 9 10
# attr(,"original.script")
# [1] "this.is.the.name"

Related

How to loop through urls in a column using download.file()

I have this df from which I need to download all file urls:
library(RCurl)
view(df)
Date column_1
<chr> <chr>
1 5/1/21 https://this.is.url_one.tar.gz
2 5/2/12 https://this.is.url_two.tar.gz
3 7/3/19 https://this.is.url_three.tar.gz
4 8/3/13 https://this.is.url_four.tar.gz
5 10/1/17 https://this.is.url_five.tar.gz
6 12/12/10 https://this.is.url_six.tar.gz
7 9/9/16 https://this.is.url_seven.tar.gz
8 4/27/20 https://this.is.url_eight.tar.gz
9 7/20/15 https://this.is.url_nine.tar.gz
10 8/30/19 https://this.is.url_ten.tar.gz
# … with 30 more rows
Of course I do not want to type download.file(url='https://this.is.url_number.tar.gz', destfile='files.tar.gz', method='curl') 40 times for each url. How can I loop over all url's in column_1 using download.file()?
Here is one way in a forloop
for(i in seq_len(nrow(df))) {
download.file(url = df$column_1[i],
destfile = paste0('files', df$column_ID_number[i],
'.tar.gz'), method = 'curl')
}
You can use Map -
Map(download.file, df$column_1, sprintf('file%d.tar.gz', seq(nrow(df))))
where sprintf is used to create filenames to save the file.

R readRDS file through shortcut

I've created a shortcut on Windows which points to a RDS file. Is there a way to 'read' the shortcut and load the file?
I've tried the following command, but failed.
readRDS("...") # with correct location
You could use R.Utils package and it's readWindowsShortcut function -> CRAN link
This is a two-step procedure, where:
Using the readWindowsShortcut() one converts a .lnk file into a list
With readRDS one extracts the relativePath element from the list
Here is a working example with a step-by-step explanation:
data <- data.frame(a = c(1,2,3,4),
b = c("a", "b", "c", "d"))
# Save to disk (in working directory)
saveRDS(data, file = "data.Rds")
##
# Create a windows link `.lnk` manally
##
# Load (install if necessary) library
library(R.utils)
# Read content of .lnk and store it to an object
path <- readWindowsShortcut("data.Rds - Shortcut.lnk")
# See what's inside `path` object
summary(path)
Length Class Mode
header 12 -none- list
fileLocationInfo 4 -none- list
relativePath 1 -none- character
workingDirectory 1 -none- character
relativePathname 1 -none- character
pathname 1 -none- character
# Read RDS from `relativePath`
readRDS(path$relativePath)
a b
1 1 a
2 2 b
3 3 c
4 4 d

R: trouble assigning values to a dynamic variable in a dataframe

I am trying to assign values to a dataframe variable defined by the user. The user specifies the name of the variable, let's call this x, in the dataframe df. For simplicity I want to assign a value of 3 to everything in the column the user specifies. The simplified code is:
variableName <- paste("df$", x, sep="")
eval(parse(text=variableName)) <- 3
But I get an error:
Error in file(filename, "r") : cannot open the connection
In addition: Warning message:
In file(filename, "r") :
cannot open file 'df$x': No such file or directory
I've tried all kinds of remedies to no avail. If I simply try to print the values of the column.
eval(parse(text=variableName))
I get no errors and it prints out ok. It's only when I try to give that column a value that I get the error. Any help would be appreciated.
I believe the issue is that there is no way to use the result of eval() on the LHS of an assignment.
df = data.frame(foo = 1:5,
bar = -3)
x = "bar"
variableName <- paste("df$", x, sep="")
eval(parse(text=variableName)) <- 3
#> Warning in file(filename, "r"): cannot open file 'df$bar': No such file or
#> directory
#> Error in file(filename, "r"): cannot open the connection
## This error is a bit misleading. Breaking it apart I get a different error.
eval(expression(df$bar)) <- 3
#> Error in eval(expression(df$bar)) <- 3: could not find function "eval<-"
## And it works if you put it all in the string to be parsed.
ex1 <- paste0("df$", x, "<-3")
eval(parse(text=ex1))
df
#> foo bar
#> 1 1 3
#> 2 2 3
#> 3 3 3
#> 4 4 3
#> 5 5 3
## But I doubt that's the best way to do it!

Missing `parse` information inside vignette build

Goal
The goal is to create a package that parses R scripts and lists functions (from the package - like mvbutils- but also imports).
Function
The main function relies on parsing R script with
d<-getParseData(x = parse(text = deparse(x)))
Reproducible code
For example in an interactive R session the output of
x<-test<-function(x){x+1}
d<-getParseData(x = parse(text = deparse(x)))
Has for first few lines:
line1 col1 line2 col2 id parent token terminal text
23 1 1 4 1 23 0 expr FALSE
1 1 1 1 8 1 23 FUNCTION TRUE function
2 1 10 1 10 2 23 '(' TRUE (
3 1 11 1 11 3 23 SYMBOL_FORMALS TRUE x
4 1 12 1 12 4 23 ')' TRUE )
Error
When building a vignette with knitr containing - either with knit html from RStudio or devtools::build_vignettes, the output of the previous chunk of code is NULL. On the other hand using "knitr::knit" inside an R session will give the correct output.
Questions:
Is there a reason for the parser to behave differently inside the knit function/environment, and is there a way to bypass this?
Update
Changing code to:
x<-test<-function(x){x+1}
d<-getParseData(x = parse(text = deparse(x),keep.source = TRUE))
Fixes the issue, but this does not answer the question of why the same function behaves differently.
From the help page ?options:
keep.source:
When TRUE, the source code for functions (newly defined or loaded) is stored internally allowing comments to be kept in the right places. Retrieve the source by printing or using deparse(fn, control = "useSource").
The default is interactive(), i.e., TRUE for interactive use.
When building the vignette, you are running a non-interactive R session, so the source code is discarded in parse().
parse(file = "", n = NULL, text = NULL, prompt = "?",
keep.source = getOption("keep.source"), srcfile,
encoding = "unknown")

could not find function "summary.rbga"

when im trying to execute the the following command:
cat(summary.rbga(GAmodel))
the output is:
Error in cat(summary.rbga(GAmodel)):
could not find function "summary.rbga"
im sure that i import the package by the command "library(genalg)" and it works perfectly for other functions.
im using Version 0.98.1102 on windows.
The function summary.rbga is in genalg but it's not exported from the package explicitly. It's the special implementation of the summary function for rbga objects. In the example from the help page, you can see how it works
evaluate <- function(string=c()) {
returnVal = 1 / sum(string);
returnVal
}
rbga.results = rbga.bin(size=10, mutationChance=0.01, zeroToOneRatio=0.5,
evalFunc=evaluate)
class(rbga.results)
# [1] "rbga"
summary(rbga.results, echo=TRUE)
# GA Settings
# Type = binary chromosome
# Population size = 200
# Number of Generations = 100
# Elitism = 40
# Mutation Chance = 0.01
#
# Search Domain
# Var 1 = [,]
# Var 0 = [,]
#
# GA Results
# Best Solution : 1 1 1 1 1 1 1 1 1 1
Note that you call summary rather than summary.rbga directly. As long as you pass in an object that has class "rbga" it will work.
You can access the function directly with genalg:::summary.rbga

Resources