Lacking output strings when using function in R - r

I'm having a problem with the below function:
ab<-matrix(c(1:20),nrow=4)
rownames(ab)<-c("a","b","c","d")
cd<-c("a","c")
test<-function(x,y,ID_Tag){
for(i in y) {
M_scaled<-t(scale(t(x),center=T))
a<-quantile(M_scaled[match(i,rownames(x)),])
assign(paste0("Probes_",ID_Tag,"_quan_",i),a)
}
}
test(ab,cd,"C1")
x is the dataframe/matrix
y is the string I need to search for in rownames(x)
ID_Tag is is the number I use to distinguish my samples from each other.
The function is running, but no output is generated into strings afterwards.
Hope somebody can help me

When you use assign within a function it will make the assignment to a variable that is accessible within that function only (i.e. it's like using <-). To get around this, you need to specify the envir argument in assign to be either the global environment globalenv() or the parent frame of the function. So try changing your assign statement to
assign(..., envir = parent.frame())
or
assign(..., envir = globalenv())
depending on what you want exactly (in the example you provided they are equivalent). Have a look at ?parent.frame for more info on these. Another possibility is to specify the pos argument in assign, check ?assign.
As an aside, assigning global objects from within a function can lead to various problems in general. I find it better practice in your example to return a list of objects created in the for loop rather than use assign.

Related

Why applying a customized function to replace de current value of a variable in a dataframe does not replace it permanently? [duplicate]

I am poking into the manuals, I wanted to ask the community:
How can we set global variables inside a function?
As Christian's answer with assign() shows, there is a way to assign in the global environment. A simpler, shorter (but not better ... stick with assign) way is to use the <<- operator, ie
a <<- "new"
inside the function.
I found a solution for how to set a global variable in a mailinglist posting via assign:
a <- "old"
test <- function () {
assign("a", "new", envir = .GlobalEnv)
}
test()
a # display the new value
What about .GlobalEnv$a <- "new" ? I saw this explicit way of creating a variable in a certain environment here: http://adv-r.had.co.nz/Environments.html. It seems shorter than using the assign() function.

lapply and the save function in R

I have created a list of objects in my work environment
data <- c("variable1", "variable2", "variable3")
i would like to save the files to different directories with the variable name as the directory... so i did this to give me a list of file names to pass to the save function via lapply..
paste0(data,"/",data,".rda")
lapply(data,FUN=save,file = paste0(data,"/",data,".rda"))
i get the error
Error in FUN(X[[i]], ...) : object ‘X[[i]]’ not found
i'm not sure what i'm doing wrong here..
Do you have a list of objects, or a list of names of objects? You say you have the former, but the code you give is for the latter.
Also, if you only have one object per file, then it's better to use the saveRDS function (and loadRDS to load it).
lapply(data, function(x) saveRDS(get(x), paste0(x, "/", x, ".rds")))
If you have to use save:
lapply(data, function(x) save(list=x, file=paste0(x, "/", x, ".rds")))
Several things going on here.
First, you need not use lapply when you don't care about the return value of the function called at each iteration. It offers nothing in this case.
Second, and more importantly, what you are doing is writing objects to files with names derived from their variable names in R. That's an anti-pattern.
Instead, create a list of the objects, and use for for the work. We need to use saveRDS for this (thanks Hong Ooi) as l[[n]] is also not the name of an object in the environment.
l <- list(variable1 = variable1, variable2 = variable2, variable3=variable3)
for (n in names(l)) {
fname = paste0(n, '/', n, '.rda')
saveRDS(file=fname, l[[n]])
}
It would be better to just save the entire list, but then all the data would be in one file in one directory.
As for what's actually wrong with your code:
You pass the same value for file to all invocations of save, and you don't intend to do so. This value is a vector, but what you want is that each iteration gets one element from this vector.
The way lapply computes the value to pass to the function confuses save. In particular, it does this:
names <- as.character(substitute(list(...)))[-1L]
That results in something like the following, which is not the name of an object in the environment.
c("variable1", "variable2", "variable3")[[1]]

retrieving object definition in R studio

I've been defining some variables with the "<-", like
elect<- copPob12$nivelaprob[copPob12$dispelect==5]
I can see their numerical values on the global environment,
but I want to see how I defined them, to be sure about the function I used, because they are subsets within subsets, I can find them in the "History" tab, but that takes too long,
any function that can retrieve the way I defined the variable on the console?
thanks a lot
As I see the problem, may be you are looking for this:
elect <<- copPob12$nivelaprob[copPob12$dispelect==5]
or you can write
elect <- copPob12$nivelaprob[copPob12$dispelect==5]
assign("elect", elect , envir = .GlobalEnv)
here it changes environment as global so it works within function also

How do I empty a list in R?

I have a file with an R program. I load it interactively on R and then I call the main function. During the execution I fill up some global lists but when I run the main function again I want those lists to be empty. How can I empty a filled up list? I tried doing
list <- NULL
after execution but it didn't work.
Since you are setting them globally, you probably need list <<- NULL, because the <<- operator assigns global variables.
Edit, per #Dason's comment:
The <<- operator can in some circumstances fail to change the value of a variable in all possible environments. For that reason, it is better to use
assign("list", NULL, envir = .GlobalEnv)

How do you stop source from abbreviating function names?

I am trying to source multiple functions, that differ by a number in the name.
For example: func1, func2.
I tried using "func_1", and "func_2", as well as putting the number first, "1func" and "2func". No matter how I index the function names, the source function just reads in one function that it calls "func" - which is not what I want.
I have tried using for-loops and sapply:
for-loop:
func.list <- list.files(path="/some_path",pattern="some pattern",full.names=TRUE)
for(i in 1:length(func.list)){
source(func.list[i])
}
sapply:
sapply(func.list,FUN=source)
I am going to be writing multiple versions of a data correction function, and would really like to be able to index them - because giving a concise, but specific, name would be difficult, and not allow me to selectively source just the function files from their directory.
In my code, func.list gives the output (I have replaced the actual directory because of privacy/contractual issues):
[1] "mypath/1resp.correction.R"
[2] "mypath/2resp.correction.R"
Then when I source func.list with either the for-loop or sapply code (listed above), R only loads one function named resp.correction, with the code body from "2resp.correction.R".
The argument to source is a file name, not a function name. So you cannot be fancy here: you need to provide the exact filenames.
It sounds like your two files contain the definitions of a function with the same name (resp.correction) in both files, so yes, as you source one file after the other, the function is overwritten in your global environment.
You could, inside your loop, reassign the function to a different name:
func.list <- list.files(path="/some_path",pattern="some pattern",full.names=TRUE)
for(i in 1:length(func.list)) {
source(func.list[i], local = TRUE)
assign(paste0("resp.correction", i), resp.correction, envir = .GlobalEnv)
}

Resources