Why can't R find this variable?
assign(paste0('my', '_var'), 2)
get(paste0('my', '_var')) ## isn't this returning an object?
save(get(paste0('my', '_var')), file = paste0('my', '_var.RDATA'))
This throws the error:
Error in save(paste0("my", "_var"), file = paste0("my", "_var.RDATA")) :
object ‘paste0("my", "_var")’ not found
From the help page, the save() function expects "the names of the objects to be saved (as symbols or character strings)." Those values are not evaulated, ie you can't put in functions that will eventually return strings or raw values themselves. Use the list= parameter if you want to call a function to return a string the the name of a variable.
save(list=paste0('my', '_var'), file = paste0('my', '_var.RDATA'))
Though using get/assign is often not a good practice in R. They are usually better ways so you might want to rethink your general approach.
And finally, if you are saving a single object, you might want to consider saveRDS() instead. Often that's the behavior people are expecting when they use the save() function.
The documentation for save says that ... should be
the names of the objects to be saved (as symbols or character strings).
And indeed if you type save into the console you can see that the source has the line
names <- as.character(substitute(list(...)))[-1L]
where substitute captures its argument and doesn't evaluate it. So as the error suggests, it is looking for an object with the name paste0('my', '_var'), not evaluating the expressions supplied.
Related
My question refers to redundant code and a problem that I've been having with a lot of my R-Code.
Consider the following:
list_names<-c("putnam","einstein","newton","kant","hume","locke","leibniz")
combined_df_putnam$fu_time<-combined_df_putnam$age*365.25
combined_df_einstein$fu_time<-combined_einstein$age*365.25
combined_df_newton$fu_time<-combined_newton$age*365.25
...
combined_leibniz$fu_time<-combined_leibniz$age*365.25
I am trying to slim-down my code to do something like this:
list_names<-c("putnam","einstein","newton","kant","hume","locke","leibniz")
paste0("combined_df_",list_names[0:7]) <- data.frame("age"=1)
paste0("combined_df_",list_names[0:7]) <- paste0("combined_df_",list_names[0:7])$age*365.25
When I try to do that, I get "target of assignment expands to non-language object".
Basically, I want to create a list that contains descriptors, use that list to create a list of dataframes/lists and use these shortcuts again to do calculations. Right now, I am copy-pasting these assignments and this has led to various mistakes because I failed to replace the "name" from the previous line in some cases.
Any ideas for a solution to my problem would be greatly appreciated!
The central problem is that you are trying to assign a value (or data.frame) to the result of a function.
In paste0("combined_df_",list_names[0:7]) <- data.frame("age"=1), the left-hand-side returns a character vector:
> paste0("combined_df_",list_names[0:7])
[1] "combined_df_putnam" "combined_df_einstein" "combined_df_newton"
[4] "combined_df_kant" "combined_df_hume" "combined_df_locke"
[7] "combined_df_leibniz"
R will not just interpret these strings as variables that should be created and be referenced to. For that, you should look at the function assign.
Similarily, in the code paste0("combined_df_",list_names[0:7])$age*365.25, the paste0 function does not refer to variables, but simply returns a character vector -- for which the $ operator is not accepted.
There are many ways to solve your problem, but I will recommend that you create a function that performs the necessary operations of each data frame. The function should then return the data frame. You can then re-use the function for all 7 philosophers/scientists.
I created a small function to process a dataframe to be able to use the function:
preprocessCore::normalize.quantiles()
Since normalize.quintles() can only use a matrixc object, and I need to rearrange my data, I create a small function that takes a specific column (variable) in a especific data frame and do the following:
normal<-function(boco,df){
df_p1<-subset(df,df$Plate==1)
df_p2<-subset(df,df$Plate==2)
mat<-cbind(df_p1$boco,df_p2$boco)
norm<-preprocessCore::normalize.quantiles(mat)
df_1<-data.frame(var_1=c(norm[,1],norm[,2]),well=c(df_p1$well,df_p2$well))
return(df_1)
}
However, "mat" should be a matrix, but it seems the cbind() does not do its job since I'm obtaining the following Error:
normal(antitrombina_FI,Six_Plex_IID)
Error in preprocessCore::normalize.quantiles(mat) :
Matrix expected in normalize.quantiles
So, it is clear that the cbind() is not creating a matrix. I don't understand why this is happening.
Most likely you are binding two NULL objects together, yielding NULL, which is not a matrix. If your df objects are data.frame, then df_p1$boco is interpreted as "extract the variable named boco", not "extract the variable whose name is the value of an object having the symbol boco". I suspect that your data does not contain a variable literally named "boco", so df_p1$boco is evaluated as NULL.
If you want to extract the column that is given as the value to the formal argument boco in function normal() then you should use [[, not $:
normal<-function(boco,df){
df_p1<-subset(df,df$Plate==1)
df_p2<-subset(df,df$Plate==2)
mat<-cbind(df_p1[[boco]],df_p2[[boco]])
norm<-preprocessCore::normalize.quantiles(mat)
df_1<-data.frame(var_1=c(norm[,1],norm[,2]),well=c(df_p1$well,df_p2$well))
return(df_1)
}
Thanks for your help bcarlsen. However I have found some errors:
First, I believe you need to introduce quotes in
mat<-cbind(df_p1[["boco"]],df_p2[["boco"]])
If I run this script outside of a function works erally perfectly:
df_p1<-subset(Six_Plex_IID,Six_Plex_IID$Plate==1)
df_p2<-subset(Six_Plex_IID,Six_Plex_IID$Plate==2)
mat<-cbind(df_p1[["antitrombina_FI"]],df_p2[["antitrombina_FI"]])
norm<-preprocessCore::normalize.quantiles(mat)
However If I introduce this now in a function and try to run it like a function:
normal<-function(boco,df){
df_p1<-subset(df,df$Plate==1)
df_p2<-subset(df,df$Plate==2)
mat<-cbind(df_p1[["boco"]],df_p2[["boco"]])
norm<-preprocessCore::normalize.quantiles(mat)
df_1<-data.frame(var_1=c(norm[,1],norm[,2]),well=c(df_p1$well,df_p2$well))
return(df_1)
}
normal(antitrombina_FI,Six_Plex_IID)
I get the same error mesage:
Error in preprocessCore::normalize.quantiles(mat) :
Matrix expected in normalize.quantiles
I'm completely clueless about why this is happening, why outside the function I'm obtaining a matrix and why inside the function not.
Thanks
I wanted to answer a question regarding plotmath but I failed to get my desired substitute output.
My desired output:paste("Hi", paste(italic(yes),"why not?"))
and what I get: paste("Hi", "paste(italic(yes),\"why not?\")")
text<-'paste(italic(yes),"why not?")'
text
[1] "paste(italic(yes),\"why not?\")"
noqoute_text<-noquote(text)
noqoute_text
[1] paste(italic(yes),"why not?")
sub<-substitute(paste("Hi",noqoute_text),
env=list(noqoute_text=noqoute_text))
sub
paste("Hi", "paste(italic(yes),\"why not?\")")
You're using the wrong function, use parse instead of noquote :
text<-'paste(italic(yes),"why not?")'
noquote_text <- parse(text=text)[[1]]
sub<- substitute(paste("Hi",noquote_text),env=list(noquote_text= noquote_text))
# paste("Hi", paste(italic(yes), "why not?"))
noquote just applies a class to an object of type character, with a specific print method not to show the quotes.
str(noquote("a"))
Class 'noquote' chr "a"
unclass(noquote("a"))
[1] "a"
Would you please elaborate on your answer?
In R you ought to be careful about the difference between what's in an object, and what is printed.
What noquote does is :
add "noquote" to the class attribute of the object
That's it
The code is :
function (obj)
{
if (!inherits(obj, "noquote"))
class(obj) <- c(attr(obj, "class"), "noquote")
obj
}
Then when you print it, the methods print.noquote :
Removes the class "noquote" from the object if it's there
calls print with the argument quote = FALSE
that's it
You can actually call print.noquote on a string too :
print.noquote("a")
[1] a
It does print in a similar fashion as quote(a) or substitute(a) would but it's a totally different beast.
In the code you tried, you've been substituting a string instead of a call.
For solving the question I think Moody_Mudskipperss answer works fine, but as you asked for some elaboration...
You need to be careful about different ways similar-looking things are actually stored in R, which means they behave differently.
Especially with the way plotmath handles labels, as they try to emulate the way character-strings are normally handled, but then applies its own rules. The 3 things you are mixing I think:
character() is the most familiar: just a string. Printing can be confusing when quotes etc. are escaped. The function noquote basically tells R to mark it's argument, so that quotes are not escaped.
calls are "unevaluated function-calls": it's an instruction as to what R should do, but it's not yet executed. Any errors in this call don't come up yet, and you can inspect it.
Note that a call does not have its own evironment given with it, which means a call can give different results if evaluated e.g. from within a function.
Expressions are like calls, but applied more generally, i.e. not always a function that needs to be executed. An expression can be a variable-name, but also a simple value such as "why not?". Also, expressions can consist of multiple units, like you would have with {
Different functions can convert between these classes, but sometimes functions (such as paste!) also convert unexpectedly:
noquote does not do that much useful, as Moody_Mudskipper already pointed out: it only changes the printing. But the object basically remains a character
substitute not only substitutes variables, but also converts its first argument into (most often) a call. Here, the print bites you, for when printing a call, there is no provision for special classes of its members. Try it: sub[[3]] from the question gives[1] paste(italic(yes),"why not?")
without any backslashes! Only when printing the full call the noquote-part is lost.
parse is used to transform a character to an expression. Nothing is evaluated yet, but some structure is introduced, so that you could manipulate the expression.
paste is often behaving annoyingly (although as documented), as it can only paste together character-strings. Therefore, if you feed it anything but a character, it firs calls as.character. So if you give it a call, you just get a text-line again. So in your question, even if you'd use parse, as soon as you start pasting thing together, you get the quotes again.
Finally, your problem is harder because it's using plotmaths internal logic.
That means that as soon as you try to evaluate your text, you'll probably get an error "could not find function italic" (or a more confusing error if there is a function italic defined elsewhere). When providing it in plotmath, it works because the call is only evaluated by plotmath, which will give it a nice environment, where italic works as expected.
This all means you need to treat it all as an expression or call. As long as evaluation cannot be done (as long as it's you that handles the expression, instead of plotmath) it all needs to remain an expression or call. Giving substitute a call works, but you can also emulate more closely what happens in R, with
call('paste', 'Hi', parse(text=text)[[1]])
I hope to get some help on the use of quotation marks within a string for get().
Say, I want to retrieve an element from a list
some_list <- list(element1=11,element2=22,element3=33)
naturally, I can simply reference this element through
some_list[['element1']]
However, once I use this as a string within get(), R throws this error message
get("some_list[['element1']]")
> Error in get("some_list[['element1']]") :
object 'some_list[['element1']]' not found
I cannot figure out why this is the case. get() works fine when used with strings that do not have quotation marks within them, e.g.
get("some_list")
I also tried escaping the quotation marks within the string (although I don't this I would need to since they are single quotation marks) but it does not work either.
some_list[["\'"element1"\'"]]
What am I missing.
get won't do that.
some_list[['element1']] isn't the name of an object in an R environment (in a technical sense). When you type some_list[['element1']] at the console, R parses the expression, looks up the symbol some_list and then calls the function [[. get is intended just for the symbol lookup piece of that.
(Technically, my sequence of events there probably isn't right, but I listed them that way to help make the issue clear. Really, R is just parsing the expression, and then calling [[ with arguments some_list and 'element1', and those symbols are subsequently looked up.)
The quotes have nothing to do with it. Run:
get("some_list")[['element1']]
I'm having trouble working with a data table in R. This is probably something really simple but I can't find the solution anywhere.
Here is what I have:
Let's say t is the data table
colNames <- names(t)
for (col in colNames) {
print (t$col)
}
When I do this, it prints NULL. However, if I do it manually, it works fine -- say a column name is "sample". If I type t$"sample" into the R prompt, it works fine. What am I doing wrong here?
You need t[[col]]; t$col does an odd form of evaluation.
edit: incorporating #joran's explanation:
t$col tries to find an element literally named 'col' in list t, not what you happen to have stored as a value in a variable named col.
$ is convenient for interactive use, because it is shorter and one can skip quotation marks (i.e. t$foo vs. t[["foo"]]. It also does partial matching, which is very convenient but can under unusual circumstances be dangerous or confusing: i.e. if a list contains an element foolicious, then t$foo will retrieve it. For this reason it is not generally recommended for programming.
[[ can take either a literal string ("foo") or a string stored in a variable (col), and does not do partial matching. It is generally recommended for programming (although there's no harm in using it interactively).