I have a Seurat single-cell gene expression object, which has slots.
One of the slots is #meta.data, which is a matrix.
I'd like to create a column $orig.ident by assigning it the value of meta$brain.region as a factor. meta is my original table of metadata.
I'm doing this for a bunch of datasets and would like to make it generalizable.
The idea is that the user would only have to enter the name of the original object, and everything from then on would be called accordingly.
User prompt:
> dataset <- "path/to/gw14.RData"
> seurat.obj <- "gw14"
The workspace is then loaded, which includes the Seurat object gw14.
> load(dataset)
> seurat.obj.new <- paste0(seurat.obj, ".", 2)
I don't understand why using get here returns the error below:
> get(seurat.obj.new)#meta.data$orig.ident <- factor(meta$brain.region)
Error in get(seurat.obj.new)#meta.data$orig.ident = factor(meta$brain.region) :
could not find function "get<-"
Whereas using it here works as expected:
> assign(seurat.obj.new, CreateSeuratObject(raw.data = get(seurat.obj)#raw.data,
min.cells = 0, min.genes = 0, project=age))
First, just write a function that assumes you pass in the actual data object and returns an updated data object. For example
my_fun <- function(x) {
x#meta.data$orig.ident <- factor(meta$brain.region)
x
}
Then normally you would call it like this
gw14.2 <- my_fun(gw14)
Note functions in R should return take a value and return an updated value. They should not have side effects like creating variables. That should be in the user''s control.
If you did want to work with the data objects as strings, you could do
seurat.obj <- "gw14"
seurat.obj.new <- paste0(seurat.obj, ".", 2)
assign(seurat.obj.new, my_fun(get(seurat.obj)))
But this type of behavior is not consistent with how most R functions operate.
Related
I have created a function for GWR maps and I have run the code without it being in the function and it works well. However, when I create into a function I get an error. I was wondering if anyone could help, thank you!
#a=polygonshapefile
#b= Dependent variabable of shapefile
#c= Explantory variable 1
#d= Explantory vairbale 2
GWR_map <- function(a,b,c,d){
GWRbandwidth <- gwr.sel(a$b ~ a$c+a$d, a,adapt=T)
gwr.model = gwr(a$b ~ a$c+a$d, data = a, adapt=GWRbandwidth, hatmatrix=TRUE, se.fit=TRUE)
gwr.model
}
GWR_map(OA.Census,"Qualification", "Unemployed", "White_British")
The above code produces the following error:
Error in model.frame.default(formula = a$b ~ a$c + a$d, data = a, drop.unused.levels = TRUE) :
invalid type (NULL) for variable 'a$b'
You can't use function parameters with the $. Try changing your function to use the [[x]] notation instead. It should look like this:
GWR_map <- function(a,b,c,d){
GWRbandwidth <- gwr.sel(a[[b]] ~ a[[c]]+a[[d]], a,adapt=T)
gwr.model = gwr(a[[b]] ~ a[[c]]+a[[d]], data = a, adapt=GWRbandwidth, hatmatrix=TRUE, se.fit=TRUE)
gwr.model
}
The R help docs (section 6.2 on lists) explain this difference well:
Additionally, one can also use the names of the list components in double square brackets,
i.e., Lst[["name"]] is the same as Lst$name. This is especially useful, when the name of the component to be extracted is stored in another variable as in
x <- "name"; Lst[[x]] It is very important to distinguish Lst[[1]] from Lst[1]. ‘[[...]]’ is the operator used to select a single element, whereas ‘[...]’ is a general subscripting operator. Thus the former is the first object in the list Lst, and if it is a named list the name is not included. The latter
is a sublist of the list Lst consisting of the first entry only. If it is a named list, the names are transferred to the sublist.
In my code there is a situation where I conditionally want to use one accessor function or another throughout the code. Instead of having an if-else statement for every time I want to pick which accessor to use and coding it explicitly, I tried to conditionally assign either of the accessor functions to a new function called accessor_fun and use it throughout the code, but this returns an error when I use the accessor function to reassign the values it accesses. Here is a simplified example of the problem I am having:
#reassigning the base r function names to a new function name
alt_names_fun <- names
example_list <- list(cat = 7, dog = 8, fish = 33)
other_example_list <- list(table = 44, chair = 101, desk = 35)
#works
alt_names_fun(example_list)
#throws error
alt_names_fun(example_list) <- alt_names_fun(other_example_list)
#still throws error
access_and_assign <- function(x, y, accessor) {
accessor(x) <- accessor(y)
}
access_and_assign(x = example_list, y = other_example_list, accessor = alt_names_fun)
#still throws error
alt_names_fun_2 <- function(x){names(x)}
alt_names_fun_2(example_list) <- alt_names_fun_2(other_example_list)
#works
names(example_list) <- names(other_example_list)
As you see if you try the code above, an example of the kind of error I am getting is
Error in alt_names_fun(example_list) <- alt_names_fun(other_example_list) :
could not find function "alt_names_fun<-"
So my question is, is there a way to do the reassignment of R accessor functions and use them in a way like I am trying to in the example above?
Accessor functions are really pairs of functions. One for retrieval and one for assignment. If you want to replicate that, you need to replicate both parts
alt_names_fun <- names
`alt_names_fun<-` <- `names<-`
The assignment versions have <- in their name. This is a special naming convection that R uses to find them. Since these are character normally not allowed in basic symbol names, you need to use the back ticks to enclose the function names.
I have to run 10's of different permutations with same structure but different base names for the output. to avoid having to keep replacing the whole character names within each formula, I was hoping to great a variable then use paste function to assign the variable to the name of the output..
Example:
var<-"Patient1"
(paste0("cells_", var, sep="") <- WhichCells(object=test, expression = test > 0, idents=c("patient1","patient2"))
The expected output would be a variable called "cells_Patient1"
Then for subsequent runs, I would just copy and paste these 2 lines and change var <-"Patient1" to var <-"Patient2"
[please note that I am oversimplifying the above step of WhichCells as it entails ~10 steps and would rather not have to replace "Patient1" by "Patient2" using Search and Replaced
Unfortunately, I am unable to crate the variable "cells_Patient1" using the above command. I am getting the following error:
Error in variable(paste0("cells_", var, sep = "")) <-
WhichCells(object = test, : target of assignment expands to
non-language object
Browsing stackoverflow, I couldn't find a solution. My understanding of the error is that R can't assign an object to a variable that is not a constant. Is there a way to bypass this?
1) Use assign like this:
var <- "Patient1"
assign(paste0("cells_", var), 3)
cells_Patient1
## [1] 3
2) environment This also works.
e <- .GlobalEnv
e[[ paste0("cells_", var) ]] <- 3
cells_Patient1
3) list or it might be better to make these variables into a list:
cells <- list()
cells[[ var ]] <- 3
cells[[ "Patient1" ]]
## [1] 3
Then we could easily iterate over all such variables. Replace sqrt with any suitable function.
lapply(cells, sqrt)
## $Patient1
## [1] 1.732051
I want to create a function who create a name depending of its argument.
I tried:
a <- function(x){ assign(paste("train",x,sep=""),4]) }
But when i do a(3) for example, nothing happens. what's wrong?
Thanks for your help.
edit: I will be more specific as requested.
I want to do a feature selection: the idea is to use a function to generate different subsets of features, generate a training set for each subset, then use the output of this function in another function (let's say lm() ) to test each training set. the number of subsets/training set is variable and I don't know how to store them in order to re-use them later.
You need to assign the variable within the global environment (or whichever environment you want the variable to live in).
> a <- function(x) { assign(paste('train', x, sep = ''), 4, envir = .GlobalEnv) }
> ls()
[1] "a"
> a(1)
> ls()
[1] "a" "train1"
I currently have a basic script written in R, which has two functions embedded within another:
FunctionA <- Function() {
results_from_B <- FunctionB()
results_from_C <- FunctionC()
}
Function B generates some data which is then analysed in Function C.
If I stop the code within function A, I can see the structure of results_from_C - this appears under 'values' and I can refer to different elements using the syntax results_from_C$column_name1.
I achieved this within Function C by specifying the returned values using:
return(list(column_name_1 = value1, column_name_2 = value2)
However, I cannot work out how I can return these same values (in the same structure) from Function A - everything I try returns a list which is formatted as 'Data' rather than 'Values' and cannot be indexed using the syntax results_from_A$column_name1.
Can anyone help me to understand what I need to do in order to extract results from Function C outside of Function A?
Thanks in advance
I don't understand what you mean by formatted as 'Data' rather than 'Values'.
There's nothing wrong with the setup you describe, I every now and then use functions inside functions, it's perfectly OK.
(Note that R is case sensitive, it's function not Function.)
FunctionA <- function() {
FunctionB <- function() 1:2*pi
FunctionC <- function(x)
list(column_name_1 = x[1], column_name_2 = x[2])
results_from_B <- FunctionB()
results_from_C <- FunctionC(results_from_B)
results_from_C
}
result <- FunctionA()
result
$column_name_1
[1] 3.141593
$column_name_2
[1] 6.283185
result$column_name_1
[1] 3.141593
Is this it? If not, please clarify your question.