This question already has an answer here:
Order of operator precedence when using ":" (the colon)
(1 answer)
Closed 5 months ago.
I am a beginner in R. I was wondering why 1:n-1 1:(n-1) would come out different output?
n = 4
1:n-1
[1]0 1 2 3
n = 4
1:(n-1)
[1]1 2 3
Thanks a lot.
It is related to the precedence of operators in R (see https://stat.ethz.ch/R-manual/R-devel/library/base/html/Syntax.html)
As we can see, : has higher precedence than +- (add, substract), that means
1:n-1 is actually (1:n)-1, which is definitely different from 1:(n-1)
You need to put n-1 into brackets if you want it to be evaluated first, as : is binding stronger than -. 1:n-1 evaluates 1:n first and then subtracts 1 from each element.
In your example, 1:n yields
[1] 1 2 3 4
```
Subtraction by 1 yields:
```
[1] 0 1 2 3
```
Related
This question already has an answer here:
Operator precedence of "unary minus" (-) and exponentiation (^) outside vs. inside function
(1 answer)
Closed 8 months ago.
R seems pretty comfortable with computing the odd root of a negative number
-0.2^(1/3) # returns a good number
# [1] -0.5848035
but something weird happens if you raise a vector to the 1/3.
c(-0.2, 1)^(1/3) # returns an NA for the first element
# [1] NaN 1
I'm interested in an answer that explains what is happening differently to the vector than to the negative value when provided as a numeric scalar.
I'm not looking for a workaround e.g. function(x){sign(x)*(abs(x))^(1/3)}. This answer seems to point in a good direction... how does the "^" operator think differently about vectors and scalars?
I'm not looking for a workaround e.g. function(x) {sign(x) * (abs(x)) ^ (1/3)}.
I'm interested in an answer that explains what is happening differently to the vector than to the negative value when provided as a numeric scalar.
how does the ^ operator think differently about vectors and scalars?
You seem to believe that c(-0.2, 1)^(1/3) translates to c(-0.2^(1/3), 1^(1/3)). This is incorrect. Operator ^ is actually a function, that is, (a) ^ (b) is as same as "^"(a, b). Therefore, the correct interpretation goes as follows:
c(-0.2, 1)^(1/3)
=> "^"(c(-0.2, 1), 1/3)
=> c( "^"(-0.2, 1/3), "^"(1, 1/3) )
=> c( (-0.2)^(1/3), (1)^(1/3) )
=> c( NaN, 1 )
Now, why doesn't -0.2^(1/3) give NaN? Because ^ has higher operation precedence than +, -, * and /. So as it is written, it really implies -(0.2^(1/3)) instead of (-0.2)^(1/3).
The lesson is that, to avoid buggy code, write your code as (a) ^ (b) instead of just a ^ b.
Additional Remark:
I often compare ^ and : when teaching R to my students, because they have different behaviors. But they all show the importance of protecting operands with brackets.
(-1):2
#[1] -1 0 1 2
-1:2
#[1] -1 0 1 2
-(1:2)
#[1] -1 -2
2*3:10
#[1] 6 8 10 12 14 16 18 20
(2*3):10
#[1] 6 7 8 9 10
2*(3:10)
#[1] 6 8 10 12 14 16 18 20
See ?Syntax for details of operator precedence.
This question already has an answer here:
Order of operator precedence when using ":" (the colon)
(1 answer)
Closed 4 years ago.
I have a vector and would like to extract element 3 and 4. Can you please help me understand what the logic is behind the code version without parenthesis? I appreciate your help.
a=c(1:5)
a[(2+1): 4] # with parenthesis, makes sense
[1] 3 4
a[ 2+1 : 4] # without parenthesis, what is the logic here?
[1] 3 4 5 NA
The : operator is evaluated before the + operator.
Consider
print(c(2+1:4))
This returns
[1] 3 4 5 6
Because a vector 1,2,3,4 is created, then all elements are added by 2.
R Operator Syntax and Precedence
gives an overview over the priority of R's operators. The sequence operator : comes before the arithmetic operators like + or -.
This question already has an answer here:
Why does the vector gets expanded in the loop
(1 answer)
Closed 6 years ago.
I am running into some behaviour with R that I find confusing. Does anyone have any insight into what is going on here?
Define two objects
i <- 5
nr <- 10
So i + 2 and nr + 1
> i+2
[1] 7
> nr+1
[1] 11
So to create a sequence from 7 to 11 I could do this:
7:11
But my question why does this not produce the same result?
i+2:nr+1
We already established above that it's input numbers are equivalent. Obviously I'm missing something here but I just don't know what it is.
You have just discovered the prime R gotcha, namely: 1:n-1 produces the sequence 0, 1, 2, ..., n-1.
To obtain what you desire, wrap the expressions in brackets:
1:(n-1)
or use
seq.int(1, n-1)
The reason for the issue is operator precedence - ?Syntax`
I'm currently attempting to work out the GCD of two numbers (x and y) in R. I'm not allowed to use loops or if, else, ifelse statements. So i'm restricted to logical and arithmetic operators. So far using the code below i've managed to make lists of the factors of x and y.
xfac<-1:x
xfac[x%%fac==0]
This gives me two lists of factors but i'm not sure where to go from here. Is there a way I can combine the common elements in the two lists and then return the greatest value?
Thanks in advance.
Yes, max(intersect(xfac,yfac)) should give the gcd.
You have almost solved the problem. Let's take the example x <- 12 and y <- 18. The GCD is in this case 6.
We can start by creating vectors xf and yf containing the factor decomposition of each number, similar to the code you have shown:
xf <- (1:x)[!(x%%(1:x))]
#> xf
#[1] 1 2 3 4 6 12
yf <- (1:y)[!(y%%(1:y))]
#> yf
#[1] 1 2 3 6 9 18
The parentheses after the negation operator ! are not necessary due to specific rules of operator precedence in R, but I think that they make the code clearer in this case (see fortunes::fortune(138)).
Once we have defined these vectors, we can extract the GCD with
max(xf[xf %in% yf])
#[1] 6
Or, equivalently,
max(yf[yf %in% xf])
#[1] 6
so I have a loop that finds the position in the matrix where there is the largest difference in consecutive elements. For example, if thematrix[8] and thematrix[9] have the largest difference between any two consecutive elements, the number given should be 8.
I made the loop in a way that it will ignore comparisons where one of the elements is NaN (because I have some of those in my data). The loop I made looks like this.
thenumber = 0 #will store the difference
for (i in 1:nrow(thematrix) - 1) {
if (!is.na(thematrix[i]) & !is.na(thematrix[i + 1])) {
if (abs(thematrix[i] - thematrix[i + 1]) > thenumber) {
thenumber = i
}
}
}
This looks like it should work but whenever I run it
Error in if (!is.na(thematrix[i]) & !is.na(thematrix[i + 1])) { :
argument is of length zero
I tried this thing but with a random number in the brackets instead of i and it works. For some reason it only doesn't work when I use the i specified in the beginning of the for-loop. It doesn't recognize that i represents a number. Why doesn't R recognize i?
Also, if there's a better way to do this task I'd appreciate it greatly if you could explain it to me
You are pretty close but when you call i in 1:nrow(thematrix) - 1 R evaluates this to make i = 0 which is what causes this issue. I would suggest either calling i in 1:nrow(thematrix) or i in 2:nrow(thematrix) - 1 to start your loop at i = 1. I think your approach is generally pretty intuitive but one suggestion would be to frequently use the print() function to evaluate how i changes over the course of your function.
The issue is that the : operator has higher precedence than -; you just need to use parentheses around (nrow(thematrix)-1). For example,
thematrix <- matrix(1:10, nrow = 5)
##
wrong <- 1:nrow(thematrix) - 1
right <- 1:(nrow(thematrix) - 1)
##
R> wrong
#[1] 0 1 2 3 4
R> right
#[1] 1 2 3 4
Where the error message is coming from trying to access the zero-th element of thematrix:
R> thematrix[0]
integer(0)
The other two answers address your question directly, but I must say this is about the worst possible way to solve this problem in R.
set.seed(1) # for reproducible example
x <- sample(1:10,10) # numbers 1:10 in random order
x
# [1] 3 4 5 7 2 8 9 6 10 1
which.max(abs(diff(x)))
# [1] 9
The diff(...) function calculates sequential differences, and which.max(...) identifies the element number of the maximum value in a vector.