This is a beginner's question.
What's the difference between ^ and **?
For example:
2 ^ 10
[1] 1024
2 ** 10
[1] 1024
Is there a function such as power(x,y)?
1: No difference. It is kept around to allow old S-code to continue to function. This is documented a "Note" in ?Math?Arithmetic
2: Yes: But you already know it:
`^`(x,y)
#[1] 1024
In R the mathematical operators are really functions that the parser takes care of rearranging arguments and function names for you to simulate ordinary mathematical infix notation. Also documented at ?Math.
Edit: Let me add that knowing how R handles infix operators (i.e. two argument functions) is very important in understanding the use of the foundational infix "[[" and "["-functions as (functional) second arguments to lapply and sapply:
> sapply( list( list(1,2,3), list(4,3,6) ), "[[", 1)
[1] 1 4
> firsts <- function(lis) sapply(lis, "[[", 1)
> firsts( list( list(1,2,3), list(4,3,6) ) )
[1] 1 4
Related
If one is to create their own infix function, it needs to have the form %fun_name%. Why isn't that the case with := of tidyverse? Also, the same with the operator !!, also form tidyverse.
These operators are not functions. They are only meaningful when supplied as part of arguments to functions that use non-standard evaluation and know how to handle them. The R interpreter does not treat these operators as functions and you cannot call them directly. If you call !!something outside of a quasiquoted argument the interpreter treats it as:
!(!(something))
If you call := outside of a quasiquoted argument you get an exception.
As an aside, you can always overload base infix functions or define new S3 methods for them without needing %. The interpreter always treats these symbols as infix functions and they are not reserved. e.g:
> `+` <- function(x,y) x - y
> 1 + 2
[1] -1
`/.foo` <- function(x, y) x * y
> my_object <- structure(1, class = "foo")
> 1 / 2
[1] 0.5
> my_object / 2
[1] 2
attr(,"class")
[1] "foo"
For some reason R does allows the definition of a function := and will evaluate the resulting function as an infix function. However, this is not how rlang or data.table actually implement :=. Other symbols that begin with :, e.g. :+, or end with =, e.g. !=, are not interpreted as infix functions; I am not sure why this should be the case, as the symbol := is not used in base R. The interpreter's unique ability to evaluate it as an infix function is unexpected, at least to me.
> `:=` <- function(x,y) x - y
> 5 := 2
[1] 3
I've seen the function lapply used in R to extract elements from matrices that exist in a list of matrices.
E.g. I have a list of 3 (2x2) matrices, and I want to extract element [1,2] from each of those 3 matrices.
The code: list1 = lapply(mylist, '[', 1,2) works just fine. It returns a list with those 3 elements.
I am trying to research what this is exactly doing. Google hasn't helped and using ?'[' in the R help isn't too explanatory. I don't see how '[' is a function in R, so the code is not intuitive.
The square brackets are in fact a function whose first argument is the object being subsetted. Subsequent arguments are the index to that subset.
# For example, if M is a matrix
M[1, 2] # extracts the element at row 1, col 2
# is the same as
`[`(M, 1, 2)
# Try them!
Now, Have a look at the arguments to lapply:
args(lapply)
# function (X, FUN, ...)
Everything represented in those dots gets passed on to the function FUN as arguments.
Thus, when FUN="[", the first argument to "[" is the current element of the list (being iterated over), ie, the object being subsetted. While the subsequent arguments are the indexes to "["
Operators in R are just functions.
These are equivalent:
> x <- list(a=1,b=2)
> x[1]
$a
[1] 1
> `[`(x,1)
$a
[1] 1
The backticks are necessary only to prevent interpretation by the parser (e.g. to tell it it's a function name not to start interpreting the [ prematurely).
Being a function, it follows the same object-oriented rules (in this case, S3) as everything else.
> methods(`[`)
[1] [.acf* [.arrow* [.AsIs [.bibentry* [.cluster* [.data.frame [.data.table*
[8] [.Date [.difftime [.envlist* [.factor [.formula* [.fractions* [.getAnywhere*
[15] [.gList* [.gpar* [.gtable* [.hexmode [.idf* [.indexed* [.insensitive*
[22] [.ITime* [.listof [.noquote [.numeric_version [.octmode [.pdf_doc* [.person*
[29] [.POSIXct [.POSIXlt [.quoted* [.raster* [.roman* [.shingle* [.simple.list
[36] [.split* [.terms* [.trellis* [.ts* [.tskernel* [.uneval* [.unit*
[43] [.unit.arithmetic* [.unit.list* [.vpPath*
Non-visible functions are asterisked
+, =, etc. and other operators all work this way as well.
I've seen the function lapply used in R to extract elements from matrices that exist in a list of matrices.
E.g. I have a list of 3 (2x2) matrices, and I want to extract element [1,2] from each of those 3 matrices.
The code: list1 = lapply(mylist, '[', 1,2) works just fine. It returns a list with those 3 elements.
I am trying to research what this is exactly doing. Google hasn't helped and using ?'[' in the R help isn't too explanatory. I don't see how '[' is a function in R, so the code is not intuitive.
The square brackets are in fact a function whose first argument is the object being subsetted. Subsequent arguments are the index to that subset.
# For example, if M is a matrix
M[1, 2] # extracts the element at row 1, col 2
# is the same as
`[`(M, 1, 2)
# Try them!
Now, Have a look at the arguments to lapply:
args(lapply)
# function (X, FUN, ...)
Everything represented in those dots gets passed on to the function FUN as arguments.
Thus, when FUN="[", the first argument to "[" is the current element of the list (being iterated over), ie, the object being subsetted. While the subsequent arguments are the indexes to "["
Operators in R are just functions.
These are equivalent:
> x <- list(a=1,b=2)
> x[1]
$a
[1] 1
> `[`(x,1)
$a
[1] 1
The backticks are necessary only to prevent interpretation by the parser (e.g. to tell it it's a function name not to start interpreting the [ prematurely).
Being a function, it follows the same object-oriented rules (in this case, S3) as everything else.
> methods(`[`)
[1] [.acf* [.arrow* [.AsIs [.bibentry* [.cluster* [.data.frame [.data.table*
[8] [.Date [.difftime [.envlist* [.factor [.formula* [.fractions* [.getAnywhere*
[15] [.gList* [.gpar* [.gtable* [.hexmode [.idf* [.indexed* [.insensitive*
[22] [.ITime* [.listof [.noquote [.numeric_version [.octmode [.pdf_doc* [.person*
[29] [.POSIXct [.POSIXlt [.quoted* [.raster* [.roman* [.shingle* [.simple.list
[36] [.split* [.terms* [.trellis* [.ts* [.tskernel* [.uneval* [.unit*
[43] [.unit.arithmetic* [.unit.list* [.vpPath*
Non-visible functions are asterisked
+, =, etc. and other operators all work this way as well.
Because this would simplify my code only slightly, I'm mainly asking out of curiosity. Say you have a function
f <- function(x) {
c(x[1] - x[2],
x[2] - x[3],
x[3] - x[1])
}
Is there a way of finding out the dimension of the input required, e.g.
dim(f) = 3
Here's a very questionable solution that involves computing on the language.
I've written three functions that allow matching, searching, and extracting pieces of parse trees based on a sort of "template" parse tree piece. Here they are:
ptlike <- function(lhs,rhs,wcs='.any.',wcf=NULL) if (is.symbol(rhs) && as.character(rhs)%in%wcs) !is.function(wcf) || isTRUE(wcf(lhs,as.character(rhs))) else typeof(lhs) == typeof(rhs) && length(lhs) == length(rhs) && if (is.call(lhs)) all(sapply(seq_along(lhs),function(i) ptlike(lhs[[i]],rhs[[i]],wcs,wcf))) else lhs == rhs;
ptfind <- function(ptspace,ptpat,wcs='.any.',wcf=NULL,locf=NULL,loc=integer(),ptspaceorig=ptspace) c(list(),if (ptlike(ptspace,ptpat,wcs,wcf) && (!is.function(locf) || isTRUE(locf(ptspaceorig,loc)))) list(loc),if (is.call(ptspace)) do.call(c,lapply(seq_along(ptspace),function(i) ptfind(ptspace[[i]],ptpat,wcs,wcf,locf,c(loc,i),ptspaceorig))));
ptextract <- function(ptspace,ptpat,gets='.get.',wcs='.any.',wcf=NULL,locf=NULL,getf=NULL) { getlocs <- do.call(c,lapply(gets,function(get) ptfind(ptpat,as.symbol(get),character()))); if (length(getlocs)==0L) getlocs <- list(integer()); c(list(),do.call(c,lapply(ptfind(ptspace,ptpat,unique(c(gets,wcs)),wcf,locf),function(loc) do.call(c,lapply(getlocs,function(getloc) { cloc <- c(loc,getloc); ptget <- if (length(cloc)>0) ptspace[[cloc]] else ptspace; if (!is.function(getf) || isTRUE(getf(if (missing(ptget)) substitute() else ptget,loc,getloc,as.character(ptpat[[getloc]])))) list(if (missing(ptget)) substitute() else ptget); }))))); };
ptlike() matches two parse tree pieces against each other, allowing for wildcards on the RHS to match anything. For example:
ptlike(1L,2L);
## [1] FALSE
ptlike(1L,1L);
## [1] TRUE
ptlike(quote(a),quote(b));
## [1] FALSE
ptlike(quote(a),quote(a));
## [1] TRUE
ptlike(quote(sum(a+1)),quote(sum(b+1)));
## [1] FALSE
ptlike(quote(sum(a+1)),quote(sum(.any.+1)));
## [1] TRUE
ptlike(quote(sum(a+1)),quote(.any.(a+1)));
## [1] TRUE
ptlike(quote(sum(a+1)),quote(.any.));
## [1] TRUE
ptfind() returns a recursive index vector for each match of a parse tree pattern (RHS, if you like) in a given parse tree space (LHS), combined into a list. For example:
sp <- quote({ a+b*c:d; e+f*g:h; });
ptfind(sp,quote(.any.:.any.));
## [[1]]
## [1] 2 3 3
##
## [[2]]
## [1] 3 3 3
##
sp[[c(2L,3L,3L)]];
## c:d
sp[[c(3L,3L,3L)]];
## g:h
ptextract() is similar to ptfind(), but returns the matched piece of the parse tree space or a subset thereof:
ptextract(sp,quote(c:d));
## [[1]]
## c:d
##
ptextract(sp,quote(.any.:.any.));
## [[1]]
## c:d
##
## [[2]]
## g:h
##
ptextract(sp,quote(.any.:.get.));
## [[1]]
## d
##
## [[2]]
## h
##
So what we can do is extract from (the parse tree that comprises the body of) your function all the subscripts of the x argument and get the maximum literal subscript value:
f <- function(x) c(x[1L]-x[2L],x[2L]-x[3L],x[3L]-x[1L]);
max(unlist(Filter(is.numeric,ptextract(body(f),quote(x[.get.])))));
## [1] 3
The Filter(is.numeric,...) piece isn't really necessary here, since all subscripts are literal numbers (doubles in your definition, integers in mine, although that's inconsequential), but if there were ever non-numeric-literal subscripts, then it would be necessary.
Caveats:
It's absurd.
It would not take into account variable subscripts that might rise above the maximum literal subscript value in the parse tree. (Although, strictly speaking, in the general case, it is impossible to statically analyze all possible subscripts that might occur at run-time, due to the halting problem or something.)
If the vector was ever assigned to a different variable name, say y, and then that variable was indexed with a different subscript, even a numeric literal subscript, this algorithm would not take that into account.
And there's probably some more.
Here is my code:
x<-c(1,2)
x
names(x)<- c("bob","ed")
x$ed
Why do I get the following error?
Error in x$ed : $ operator is invalid for atomic vectors
From the help file about $ (See ?"$") you can read:
$ is only valid for recursive objects, and is only discussed in the section below on recursive objects.
Now, let's check whether x is recursive
> is.recursive(x)
[1] FALSE
A recursive object has a list-like structure. A vector is not recursive, it is an atomic object instead, let's check
> is.atomic(x)
[1] TRUE
Therefore you get an error when applying $ to a vector (non-recursive object), use [ instead:
> x["ed"]
ed
2
You can also use getElement
> getElement(x, "ed")
[1] 2
The reason you are getting this error is that you have a vector.
If you want to use the $ operator, you simply need to convert it to a data.frame. But since you only have one row in this particular case, you would also need to transpose it; otherwise bob and ed will become your row names instead of your column names which is what I think you want.
x <- c(1, 2)
x
names(x) <- c("bob", "ed")
x <- as.data.frame(t(x))
x$ed
[1] 2
Because $ does not work on atomic vectors. Use [ or [[ instead. From the help file for $:
The default methods work somewhat differently for atomic vectors, matrices/arrays and for recursive (list-like, see is.recursive) objects. $ is only valid for recursive objects, and is only discussed in the section below on recursive objects.
x[["ed"]] will work.
Here x is a vector.
You need to convert it into a dataframe for using $ operator.
x <- as.data.frame(x)
will work for you.
x<-c(1,2)
names(x)<- c("bob","ed")
x <- as.data.frame(x)
will give you output of x as:
bob 1
ed 2
And, will give you output of x$ed as:
NULL
If you want bob and ed as column names then you need to transpose the dataframe like x <- as.data.frame(t(x))
So your code becomes
x<-c(1,2)
x
names(x)<- c("bob","ed")
x$ed
x <- as.data.frame(t(x))
Now the output of x$ed is:
[1] 2
You get this error, despite everything being in line, because of a conflict caused by one of the packages that are currently loaded in your R environment.
So, to solve this issue, detach all the packages that are not needed from the R environment. For example, when I had the same issue, I did the following:
detach(package:neuralnet)
bottom line: detach all the libraries no longer needed for execution... and the problem will be solved.
This solution worked for me
data<- transform(data, ColonName =as.integer(ColonName))
Atomic collections are accessible by $
Recursive collections are not. Rather the [[ ]] is used
Browse[1]> is.atomic(list())
[1] FALSE
Browse[1]> is.atomic(data.frame())
[1] FALSE
Browse[1]> is.atomic(class(list(foo="bar")))
[1] TRUE
Browse[1]> is.atomic(c(" lang "))
[1] TRUE
R can be funny sometimes
a = list(1,2,3)
b = data.frame(a)
d = rbind("?",c(b))
e = exp(1)
f = list(d)
print(data.frame(c(list(f,e))))
X1 X2 X3 X2.71828182845905
1 ? ? ? 2.718282
2 1 2 3 2.718282