I have created a function and passing data frame as a parameter to the function. Now, I would like to take that data frame name as a string and store it into as a string variable.
Code used:
RFun <- function(a){
args=(commandArgs(TRUE))
l<<-80
h<<-85
fname<<-paste(a,"_Temp.csv")
a_R<-filter(a_RW,cs==2|cs==3)
a_R<-a_Rinse[-c(2,3)]
write.csv(a_R,file=fname,row.names=FALSE)
a_Rinse_Temperature_Deviations <- read.csv(paste("~/",fname"))
}
RFun(df)
From the above function when I try to execute it is creating numeric variables l and h with values which I have specified, but fname is creating for the complete data frame with rows and columns and it is not storing as I require here.
It is taking lot of time for execution as well.
Expected fname should be df_Temp.csv. Where df is the data frame.
Looks like assign(String varName , obj Value) might get you where you need to be.
RFun<-function(a){
args=(commandArgs(TRUE))
l<<-80
h<<-85
fname <<- "File_Name_Text"
assign (fname,paste(a,"_Temp.csv"))
a_R<-filter(a_RW,cs==2|cs==3)
a_R<-a_Rinse[-c(2,3)]
write.csv(a_R,file=fname,row.names=FALSE)
a_Rinse_Temperature_Deviations <- read.csv(paste("~/",fname))
}
It's hard to follow without a working example. But try to assign only the "name" of your df instead of the complete df. Try this:
fname <<- paste(deparse(substitute(a)),"_Temp.csv",sep="")
Related
I have been trying to create a function which will permanently change a value in specific cells of my data frame. I insert the data frame name, row index I wish to change, and the new name as a string. However, the function seems to change the value name within the local environment but not global.
The function is as follows:
#change name function
name_change <- function(df, row, name) {
df[row, 1] = name
return(df[row, 1])
}
E.g. if data frame was:
Name
Column B
Mark
2
Beth
4
The function name_change(df, 2, 'Jess') would change Beth to Jess.
When inserted as raw code it does permanently change the value. But then does not work when used as a function.
df[2, 1] = 'Jess'
Thanks in advance for your time
If you change your function like this:
name_change <- function(df, row, name) {
df[row, 1] = name
return(df)
}
and then assign the result of the function back to the original df, you will get the change you are looking for:
df = name_change(df,2,'Jess')
An alternative to the solutions already provided is to use the superassignment operator <<-. The ordinary assignment <- (or '=' you used) operate in your function's environment only. The superassignment reaches beyond your function's closure and can thus modify the dataframe residing in the global environment. Note, though, this is a quick'n'dirty fix only.
That said, the code would read like this:
#change name function
dirty_name_change <- function(df, row, name) {
df[row, 1] <<- name ## note the double arrow
}
You are returning the value of the cell, not the mutated df. R passes by arguments by value so you can imagine the function modifying a copy of df passed in. The solution is to return the mutated df and reassign it.
Can you pass-by-reference in R?
I have a data frame named data, which contains names of cryptos and their values. I also have the following function:
for(i in 1) {
x <- data$id[i] #id is the column with crypto names (such as "bitcoin")
c1 <- data[data$id == x,5] #5 is the column with values
}
c1 #returns the value of a crypto
For i in 1, it returns the value of the first crypto, for i in 2 value of the second crypto, and so on.
I would like to create a function that would return the value of any crypto-currency from the list by entering its name (id), so that it would work like this:
function("bitcoin")
#Returns the value of a crypto just like c1 above
Please, let me know how can I possibly do this.
A simple solution with some toy data:
crypto <- data.frame(name=c("bitcoin","etherium","solana","polcadot","elrond"),value=c(50000,2500,34,27,147))
crypto_values <- function(cryptoName){
value <- crypto[crypto$name==cryptoName,"value"]
return(value)
}
crypto_values("bitcoin")
[1] 50000
You have to be sure to write the right name as input.
Remember R is case-sensitive, so "bitcoin"! = "Bitcoin".
Also, note that this function is very very simple in this form, but with little effort, it can be improved so that it is not case-sensitive for example, or to make it more generic
I'm assigning a data frame to a variable name taken from a string.
So when I run the code I don't know what the variable name will be.
I want to pass that data frame to another function to plot it. How can I pass it to the function without knowing its name?
file_name <- file.choose()
fname <- unlist (strsplit (file_name, "\\", fixed = TRUE))
fname <- fname[length(fname)]
waf_no <- unlist (strsplit (fname, "\\s"))
waf_no <- waf_no[grep(waf_no, pattern="WAF")]
data <- read_WAF_file (file_name)
assign(waf_no, flux_calc(data)) #flux calc() calculates and manipulates the data frame
plot_waf(?)
my plot_waf function is very simple
plot_waf <- function (dataframe) {
library("ggplot2")
qplot(dist,n2o,data=dataframe,shape=treat)
}
The inverse for assign is get:
Search by name for an object (get) or zero or more objects (mget).
Therefore, you'll need to run your plot function like this:
plot_waf(get(waf_no))
Here is what I would expect the function to do:
datalist <- c("var1","var2",...)
my.function <- function(datalist){
n <- length(dlist)
varnames <- paste("data", dlist, sep = ".")
for (...) { # for each var in 'varnames'
... # grab each variable from some specific online dataset;
... # do some basic data manipulation for each variable
}
... # return all the results
}
The main difficulty for me is:
(1) how to do the loop so the grabbed data could be properly temporally stored, and
(2) how the multiple variables could be returned, after finishing the loop;
EDIT:
The loop can create variables I want during the loop, say VAR1 and VAR2, which were stored in the 'dlist' argument, but I cannot manipulate VAR1 or VAR2 in the function, dlist[1] or dlist[2] in the function would only give me a string but not the variable itself.
Thanks in advance.
I think I have solved the problem and make the function work as I expected.
As I described in the question, the main problem in fact is how to manipulate the variables while VAR1 and VAR2 themselves are strings in the function.
eval combined with as.name should work:
eval(as.name(dlist[i]))
Sometimes I have code which references a specific dataset based on some variable ID. I have then been creating lines of code using paste0, and then eval(parse(...)) that line to execute the code. This seems to be getting sloppy as the length of the code increases. Are there any cleaner ways to have dynamic data reference?
Example:
dataset <- "dataRef"
execute <- paste0("data.frame(", dataset, "$column1, ", dataset, "$column2)")
eval(parse(execute))
But now imagine a scenario where dataRef would be called for 1000 lines of code, and sometimes needs to be changed to dataRef2 or dataRefX.
Combining the comments of Jack Maney and G.Grothendieck:
It is better to store your data frames that you want to access by a variable in a list. The list can be created from a vector of names using get:
mynames <- c('dataRef','dataRef2','dataRefX')
# or mynames <- paste0( 'dataRef', 1:10 )
mydfs <- lapply( mynames, get )
Then your example becomes:
dataset <- 'dataRef'
mydfs[[dataset]][,c('column1','column2')]
Or you can process them all at once using lapply, sapply, or a loop:
mydfs2 <- lapply( mydfs, function(x) x[,c('column1','column2')] )
#G.Grothendieck has shown you how to use get and [ to elevate a character value and return the value of a named object and then reference named elements within that object. I don't know what your code was intended to accomplish since the result of executing htat code would be to deliver values to the console, but they would not have been assigned to a name and would have been garbage collected. If you wanted to use three character values: objname, colname1 and colname2 and those columns equal to an object named after a fourth character value.
newname <- "newdf"
assign( newname, get(dataset)[ c(colname1, colname2) ]
The lesson to learn is assign and get are capable of taking character character values and and accessing or creating named objects which can be either data objects or functions. Carl_Witthoft mentions do.call which can construct function calls from character values.
do.call("data.frame", setNames(list( dfrm$x, dfrm$y), c('x2','y2') )
do.call("mean", dfrm[1])
# second argument must be a list of arguments to `mean`