R function to use passed object name+ another name inside - r

I want to build a function that calls another object that name is related to the main object name.
For example, Main object is 'VCU_Players' and the other object is 'VCU_Players_opp'
in my function i need to use both objects in my calculations.
So i am trying to do
my_function<- function(x) {
y<-deparse(substitute(x))
z<-"_opp"
y<- paste(y,z,sep = "")
#My Calculations
x$newfield<- x$pts+ y$pts
Return(x)
}
Now i want to pass the object VCU_Players to the function
my_function(VCU_Players)
But the function doesn't figure the VCU_Players_opp object

Consider passing string literals and using get() to retrieve corresponding object:
teams <- c("Team1", "Team2", "Team3", "Team4", "Team5", "Team6",
"Team7", "Team8", "Team9", "Team10", "Team11", "Team12")
my_function <- function(i) {
x <- get(paste0(i, "_players"))
y <- get(paste0(i, "_opp"))
# My Calculations
x$newfield <- x$pts + y$pts
return(x)
}
dfList <- lapply(teams, my_function)
Ideally, however is working with a few lists of many objects, and not separate multiple objects in your global environment. Try importing from your data source (i.e., Excel) multiple objects into single lists:
teamdfs <- c(Team1_players, Team2_players, Team3_players, Team4_players, Team5_players, Team6_players,
Team7_players, Team8_players, Team9_players, Team10_players, Team11_players, Team12_players)
team_oppdfs <- c(Team1_opp, Team2_opp, Team3_opp, Team4_opp, Team5_opp, Team6_opp,
Team7_opp, Team8_opp, Team9_opp, Team10_opp, Team11_opp, Team12_opp)
my_function <- function(x, y) {
# My Calculations
x$newfield <- x$pts + y$pts
return(x)
}
dfList <- mapply(my_function, teamdfs, team_oppdfs, SIMPLIFY = FALSE)
# EQUIVALENT TO Map(my_function, teamdfs, team_oppdfs)

Related

Apply a function to objects in my global environment R

This code chunk creates a 10 objects based of length of alpha.
alpha <- seq(.1,1,by=.1)
for (i in 1:length(alpha)){
assign(paste0("list_ts_ses_tune", i),NULL)
}
How do I put each function into the new list_ts_ses_tune1 ... null objects I've created? Each function puts in a list, and works if I set list_ts_ses_tune1 <- lapply ...
for (i in 1:length(alpha))
{
list_ts_ses_tune[i] <- lapply(list_ts, function(x)
forecast::forecast(ses(x,h=24,alpha=alpha[i])))
list_ts_ses_tune[i] <- lapply(list_ts_ses_tune[i], "[", c("mean"))
}
Maybe this is a better way to do this? I need each individual output in a list of values.
Edit:
for (i in 1:length(alpha))
{
list_ts_ses_tune[[i]] <- lapply(list_ts[1:(length(list_ts)/2)],
function(x)
forecast::forecast(ses(x,h=24,alpha=alpha[i])))
list_ts_ses_tune[[i]] <- lapply(list_ts_ses_tune[[i]], "[", c("mean"))
}
We can use mget to return all the objects into a list
mget(ls(pattern = '^list_ts_ses_tune\\d+'))
Also, the NULL list can be created more easily instead of 10 objects in the global environment
list_ts_ses_tune <- vector('list', length(alpha))
Now, we can just use the OP's code
for (i in 1:length(alpha))
{
list_ts_ses_tune[[i]] <- lapply(list_ts, function(x)
forecast::forecast(ses(x,h=24,alpha=alpha[i])))
}
If we want to create a single data.frame
for(i in seq_along(alpha)) {
list_ts_ses_tune[[i]] <- data.frame(Mean = do.call(rbind, lapply(list_ts, function(x)
forecast::forecast(ses(x,h=24,alpha=alpha[i]))$mean)))
}
You could simply accomplish everything by doing:
library(forecast)
list_ts_ses_tune <- Map(function(x)
lapply(alpha, function(y)forecast(ses(x,h=24,alpha=y))['mean']), list_ts)

Addressing to subsequent objects in loop function in R

I need to create a loop function in which I need to address to subsequent objects which names end with numbers i.e. object1, object 2, object3. So the code should look like this:
object1 <- c(1,2,3,4,5)
object2 <- c(2,3,4,5,6)
object3 <- c(3,4,5,6,7)
for (i in 1:3) {
assign (paste0("new_object",i), mean(object???))
}
So I need a equivalent to just typing
new_object1 <- mean(object1)
new_object2 <- mean(object2)
new_object3 <- mean(object3)
Many thanks in advance!
It would be get to return the values of that object by pasteing the 'i' with the 'object' string
for (i in 1:3) {
assign(paste0("new_object",i), mean(get(paste0('object', i)))
}
But, it is not a recommended way as it is creating new objects in the global env.
Instead, if the intention is to get the mean of all the 'object's,
sapply(mget(paste0("object", 1:3)), mean)
Or if there are more than three, use ls with pattern
sapply(mget(ls(pattern = '^object\\d+$')), mean)
Here, mget returns the value of more than one objects in a list, loop through the list with sapply and apply the mean function on the list element.
Creating objects can also be done from the list with list2env
out <- lapply( mget(ls(pattern = '^object\\d+$')), mean)
names(out) <- paste0('new_', names(out))
list2env(out, .GlobalEnv) # not recommended based on the same reason above

How to call a data.frame inside an R Function by name

I want to write a function that runs the same analysis on different data.frames. Here is a simple version of my code:
set1 <- data.frame(x=c(1,2,4,6,2), y=c(4,6,3,56,4))
set2 <- data.frame(x=c(3,2,3,8,2), y=c(2,6,3,6,3))
mydata <- c("set1", "set2")
for (dataCount in 1:length(data)) {
lm(x~y, data=mydata)
}
How do I call a data.frame by name inside the function? Right now "data" obviously only returns the the names of "mydata" as a character.
There are number of ways of doing this. Your "native" way would be
mydata <- ls(pattern = "set")
for (dataCount in mydata) {
print(summary(lm(x~y, data=get(dataCount))))
}
or you could collate your data.frames into a list and work on that.
mylist <- list(set1, set2)
lapply(mylist, FUN = function(yourdata) {
print(summary(lm(x ~ y, data = yourdata)))
})

R: How can I make a generic function read the class of arguments passed as a list?

Imagine I created a class "stem" with some S3 methods. i need to compare a number of stem objects with a function like
comp.default = function(smpc = x){
message("I am default")
}
comp <- function(x) UseMethod("comp", x)
comp.stem = function(listOfStemObjects, print = TRUE, more args){ a bunch of things}
comp(list(stem1, stem2))
The function doesn't recognize the class because the first argument is of class "list" and not stem. Ideally I would like to pass a variable number of objects stem1, stem2,..
Any help?
Thanks in advance, marco
comp <- function(x, ...) UseMethod("comp")
comp.stem <- function(x, ...)
{
lst <- list(...)
for(i in seq_along(lst))
# do stuff with each additional object passed in
}
comp(stem1, stem2)

R: Source function by name/Import subset of functions

I have a question with importing functions.
Say I have a R script named "functions" which looks like this:
mult <- function(x,y){
return(x*y)
}
divide <- function(x,y){
return(x/y)
}
Currently I am importing all functions in the script:
source(file="C:\\functions.R",echo=FALSE)
The problem is that the (actual) R script is getting very large.
Is there a way to import the "mult" function only?
I was looking at evalSource/insertSource but my code was not working:
insertSource("C:\\functions.R", functions="mult")
It looks like your code will work with a slight change: define an empty object for the function you want to load first, then use insertSource.
mult <- function(x) {0}
insertSource("C:\\functions.R", functions="mult")
mult
Which gives:
Object of class "functionWithTrace", from source
function (x, y)
{
return(x * y)
}
## (to see original from package, look at object#original)
The mult object has some additional information that I suppose is related to the original application for insertSource, but you could get rid of them with mult <- mult#.Data, which will set mult to the actual function body only.
Also, you might be interested in the modules project on github, which is trying to implement a lightweight version of R's package system to facilitate code reuse. Seems like that might be relevant, although I think you would have to split your functions into separate files in different subdirectories.
I ended up creating functions to do what you recommended.
This first group allows for multiple functions in one call:
LoadFunction <- function(file,...) {
dots <- match.call(expand.dots = FALSE)$...
dots <- sapply(dots, as.character)
output <- lapply(dots, function(x,file){eval(parse(text=paste(x," <- function(x) {0}",sep="")),envir = .GlobalEnv)
suppressMessages(insertSource(file, functions=x))
eval(parse(text=paste(x," <- ",x,"#.Data",sep="")),envir = .GlobalEnv) },file=file)
}
UnloadFunction <- function(...) {
dots <- match.call(expand.dots = FALSE)$...
dots <- sapply(dots, as.character)
output <- lapply(dots, function(x,file){eval(parse(text=paste("rm(",x,",envir = .GlobalEnv)",sep="")))},file=file)
}
They are called like this:
LoadFunction(file="C:\\functions.R",mult,divide)
UnloadFunction(mult,divide)
The second is only one function per call:
LoadFunction2 <- function(file,function_name) {
eval(parse(text=paste(function_name," <- function(x) {0}",sep="")),envir = .GlobalEnv)
suppressMessages(insertSource(file, functions=function_name))
eval(parse(text=paste(function_name," <- ",function_name,"#.Data",sep="")),envir = .GlobalEnv)
}
UnloadFunction2 <- function(function_name) {
eval(parse(text=paste("rm(",function_name,",envir = .GlobalEnv)",sep="")))
}
They are called like this:
LoadFunction2(file="C:\\functions.R","mult")
LoadFunction2(file="C:\\functions.R","divide")
UnloadFunction2("mult")
UnloadFunction2("divide")

Resources