I am trying to write a function which does different things, depending on the second argument. But I am getting an error all the time. Depending on the dimension of the matrix, the function should perform different tasks. Here is an example
x<-cbind(X1,X2,X3)
function<-function(x,hnrstr){
if (hnrstr<-1){
x<-data.frame(X1=x[1],X2=x[2],X3=x[3])
y<-x
y[ ,"X2","X3"]<- gsub(" {2, }"," ",y[ ,"X2","X3"])
}
if (hnrstr<-2){
x<-data.frame(X1=x[1],X2=x[2])
P<-x
}
if (hnrstr<-1){
x<-y
}
if (hnrstr<-2){
x<-P
}
return(x)
}
apply(x,c(3,3), function(x,1))
I am getting the error:
Error in drop && !has.j : invalid 'x' type in 'x && y'
hnrstr<-1 is assigning the value of 1 to hnrstr. You do not want this in an if statement. You either meant "test that hnrstr is less than minus one", in which case add some whitespace. hnrstr < -1, or you meant "test that hnrstr is equal to one", in which case use double equals, hnsstr == 1.
If X1, X2 and X3 are vectors, then x will be a matrix. That is, it has two dimensions. that means that later, after you've assigned y <- x (why do you need to do this?) y[ ,"X2","X3"]) doesn't make much sense because it implies that there are 3 dimensions, not two. This is what is causing the error. Did you mean y[, c("X2","X3")])?
gsub accepts a vector, so after you've changed the previous code, you also need to change the call to that function. Do you want to pass it the second column or the third column or both (one after the other)?
Those second if blocks look pointless. Have a think about how you can remove them.
if (hnrstr<-1){
x<-y
}
if (hnrstr<-2){
x<-P
}
You don't need a return statement at the end of the function. R automatically returns the last value that was calculated in the function.
As Colin said, don't try and call your function "function". That's just asking for trouble. Change the line
function <- function(x,hnrstr){
Related
Can anyone please explain me, how am I getting the right result in R, even if the argument 'x' is not defined here:
cars<-c("Honda","Toyota","Tata","Maruti","Skoda")
car.names<-function(x){
for(name in x){
if(name=="Tata")
break
print(name)
}
}
car.names(cars)
Result: "Honda", "Toyota"
The variable x in the function is mapped to what is input in the function call, in this case cars. This means that x in the for loop is already defined as the contents of the variable cars. I think the function works because x is a vector, so the for loop runs in the positions along the vector. If you changed x to y the function should stop working as y is undefined.
Regardless of how you call the function, for example:
car.names(cars)
car.names(c("Toyota","Tata","Maruti"))
The first argument will always be known as x inside the function, because that's how it's defined in this line:
car.names <- function(x) {
}
I'm writing a code to solve a sudoku puzzle using a video found from YouTube that has coded the same algorithm through Python. This code requires three functions to
Find an empty square.
insert a number into the empty square.
Test whether this number is valid to solve the puzzle.
This is using a backtracking algorithm for the solver.
I am having an issue when calling the functions together where i get the error:
Error in free_squ(x) : argument "x" is missing, with no default
In addition: Warning message:
In if (empty_sq == FALSE) { :
the condition has length > 1 and only the first element will be used
Called from: free_squ(x)
This is confusing as I only get it when running thIS code. So I can write other functions to call the individual functions to analyse the argument inserted into the overlying function:
function1(argument){
function2(argument){
function3(argument){
***DO STUFF***}}}
Why for the following code does function within the main function not recognise the argument?
sudoku_solve <- function(x){
empty_sq <- free_squ(x) # Define a new object to give coordinates of empty square
if(empty_sq == FALSE){ # If no empty square can be found
return(x) # Return the matrix
} else{
empty_sq <- empty_sq # Pointless line kept for clarity
}
for(i in c(1:9)){ # Integers to insert into the found empty square
if(valid(x, i, empty_sq) == TRUE){ # can the intiger be placed in this square?
x[empty_sq[1], empty_sq[2]] = i # if i valid, insert into empty square
}
if(sudoku_solve()){ # are all i's valid?
return(TRUE) # All i's valid
} else{
x[empty_sq[1], empty_sq[2]] = 0 # reset the initial try and try again with another
}
}
return(FALSE)
}
I have named the sudoku puzzle 'puzzle', and call the function by the following:
sudoku_solve(puzzle)
I think in the following statement, you are not passing any value to the function and x does not have a default value either.
if(sudoku_solve()){ # are all i's valid?
return(TRUE) # All i's valid
}
Hence, although the argument is initially passed, when the function is called again after the loop, it is called without an argument. So you pass to free_sq(x) inside sudoku_solve(), and it gives an error.
empty_sq <- free_squ(x)
Make sure you are passing a value to sudoku_solve or else set the default value for x wither in sudoku_solve or in the free_squ class/function.
I am finding inconsistency in recursive function examples, so I need help clarifying its workings.
This recursive function has the argument x value be returned along with function fracrec. This fracrec gets multiplied by the original value of x. The value of it is whatever the parenthesis gives x-1 . It repeats until it exits at x == 0. Meaning that the x portion and '*' of return is the "formula" and what is used for every round.
facrec <- function(x){
if(x==0){
return(1)
} else {
return(x*facrec(x-1))
}
}
Now take this next one and there isn't anything like x and ''. So I then look at it differently since myfibrec(5) gives '5'. Taking the absolute value of the first pass would be 4+3 and already surpassing 5 with more passes still to go. There isn't any formula to go off of, so I am having difficulty understanding how the 5 came about. In the above I used the formula to be 'x' and '', which I'll admit its odd and probably incorrect.
myfibrec <- function(n) {
if(n==1||n==2){
return(1)
}else{
return(myfibrec(n-1)+myfibrec(n-2))
}
}
In yet another one, below it treats the value in the argument as the formula. This gives 2,3,4,5,6,7,8,9,10.
function Count (integer N)
if (N <= 0) return "Must be a positive integer";
if (N >9 ) return "counting completed";
else return Count (N+1);
end function
Where are all the formulas or math calculations coming from in these recursive functions?
for 'facrec' google "factorial"
for 'myfibrec' google "Fibonacci"
last one seems to be java code, not R
testing<-function(formula=NULL,data=NULL){
if(with(data,formula)==T){
print('YESSSS')
}
}
A<-matrix(1:16,4,4)
colnames(A)<-c('x','y','z','gg')
A<-as.data.frame(A)
testing(data=A,formula=(2*x+y==Z))
Error in eval(expr, envir, enclos) : object 'x' not found
##or I can put formula=(x=1)
##reason that I use formula is because my dataset had different location and I would want
##to 'subset' my data into different set
This is the main flow of my code. I had done some search and seems to be no one ask this kind of stupid question or it is not possible to pass a formula in a if statement. Thank you in advance
if you just want subset of your data.frame create a character object representing the formula like this:
formula="2*x+y==z"
testing<-function(data,formula){with(data = data,expr = eval(parse(text = formula)))}
subset(A,testing(A,formula=formula))
#x y z gg
#2 2 6 10 14
You can change the formula as per your need.
If we need to evaluate it, one option is eval(parse
testing<-function(formula=NULL,data=NULL){
data <- deparse(substitute(data))
if(any(eval(parse(text=paste("with(", data, ",",
deparse(substitute(formula)), ")")))))
print("YESSS")
}
testing(data=A,formula=(2*x+y==z))
#[1] "YESSS"
When you call a function in R it evaluates its arguments first before executing the function.
For example, prod(2+2, 3) is first turned into prod(4, 3) before the function prod() is even called.
Thus, in your code, R starts by trying to solve (2*x+y==Z). It fails because there is no x object outside of the function code. So, it not even begin running testing().
To use your function correctly you should make it clear to R that it is not supposed to calculate (2*x+y==Z). Instead it should pass this information as is. You could do that using the functions expression() and eval().
testing<-function(formula=NULL,data=NULL){
if(with(data,eval(formula==T)){
print('YESSSS')
}
}
A<-matrix(1:16,4,4)
colnames(A)<-c('x','y','z','gg')
A<-as.data.frame(A)
testing(data=A,formula=expression(2*x+y==Z))
However, you will notice that there other problems with your code.
For Z is different than z. Notice that the in colnames you use z and in the formula Z.
The if() only works for when there is a single value of true or false. In your case, you will have one value for each row in A. When this happens, if() will only check if the first row fits the criteria.
If your purpose is subsetting, it is much more easier to do:
A.subset <- subset(A, 2*A$x+A$y == A$z)
After a discussion with my colleague,
here is a kind of solution
testing<-function(cx,cy,px,py,z,data=NULL){
list<-NULL
for(m in 1:nrow(data)){
if(cx*data$x[m]^px+cy*data$y[m]^py+data$z==0){
print(m)}
}
}
but this can deal with polynomial only and with a lot of arguments in the function. I am think of a way to reduce it as a general equation.or maybe this is the most easiest equation.
I'm confused with when a value is treated as a variable, and when as a string in R. In Ruby and Python, I'm used to a string always having to be quoted, and an unquoted string is always treated as a variable. Ie.
a["hello"] => a["hello"]
b = "hi"
a[b] => a["hi"]
But in R, this is not the case, for example
a$b < c(1,2,3)
b here is the value/name of the column, not the variable b.
c <- "b"
a$c => column not found (it's looking for column c, not b, which is the value of the variable c)
(I know that in this specific case I can use a[c], but there are many other cases. Such as ggplot(a, aes(x=c)) - I want to plot the column that is the value of c, not with the name c)...
In other StackOverflow questions, I've seen things like quote, substitute etc mentioned.
My question is: Is there a general way of "expanding" a variable and making sure the value of the variable is used, instead of the name of the variable? Or is that just not how things are done in R?
In your example, a$b is syntatic sugar for a[["b"]]. That's a special feature of the $ symbol when used with lists. The second form does what you expect - a[[b]] will return the element of a whose name == the value of the variable b, rather than the element whose name is "b".
Data frames are similar. For a data frame a, the $ operator refers to the column names. So a$b is the same as a[ , "b"]. In this case, to refer to the column of a indicated by the value of b, use a[, b].
The reason that what you posted with respect to the $ operator doesn't work is quite subtle and is in general quite different to most other situations in R where you can just use a function like get which was designed for that purpose. However, calling a$b is equivalent to calling
`$`(a , b)
This reminds us, that in R, everything is an object. $ is a function and it takes two arguments. If we check the source code we can see that calling a$c and expecting R to evaluate c to "b" will never work, because in the source code it states:
/* The $ subset operator.
We need to be sure to only evaluate the first argument.
The second will be a symbol that needs to be matched, not evaluated.
*/
It achieves this using the following:
if(isSymbol(nlist) )
SET_STRING_ELT(input, 0, PRINTNAME(nlist));
else if(isString(nlist) )
SET_STRING_ELT(input, 0, STRING_ELT(nlist, 0));
else {
errorcall(call,_("invalid subscript type '%s'"),
type2char(TYPEOF(nlist)));
}
nlist is the argument you passed do_subset_3 (the name of the C function $ maps to), in this case c. It found that c was a symbol, so it replaces it with a string but does not evaluate it. If it was a string then it is passed as a string.
Here are some links to help you understand the 'why's and 'when's of evaluation in R. They may be enlightening, they may even help, if nothing else they will let you know that you are not alone:
http://developer.r-project.org/nonstandard-eval.pdf
http://journal.r-project.org/2009-1/RJournal_2009-1_Chambers.pdf
http://www.burns-stat.com/documents/presentations/inferno-ish-r/
In that last one, the most important piece is bullet point 2, then read through the whole set of slides. I would probably start with the 3rd one, then the 1st 2.
These are less in the spirit of how to make a specific case work (as the other answers have done) and more in the spirit of what has lead to this state of affairs and why in some cases it makes sense to have standard nonstandard ways of accessing variables. Hopefully understanding the why and when will help with the overall what to do.
If you want to get the variable named "b", use the get function in every case. This will substitute the value of b for get(b) wherever it is found.
If you want to play around with expressions, you need to use quote(), substitute(), bquote(), and friends like you mentioned.
For example:
x <- quote(list(a = 1))
names(x) # [1] "" "a"
names(x) <- c("", a)
x # list(foo = 1)
And:
c <- "foo"
bquote(ggplot(a, aes(x=.(c)))) # ggplot(a, aes(x = "foo"))
substitute(ggplot(a, aes(x=c)), list(c = "foo"))