Does R have a concept of += (plus equals) or ++ (plus plus) as c++/c#/others do?
No, it doesn't, see: R Language Definition: Operators
Following #GregaKešpret you can make an infix operator:
`%+=%` = function(e1,e2) eval.parent(substitute(e1 <- e1 + e2))
x = 1
x %+=% 2 ; x
R doesn't have a concept of increment operator (as for example ++ in C). However, it is not difficult to implement one yourself, for example:
inc <- function(x)
{
eval.parent(substitute(x <- x + 1))
}
In that case you would call
x <- 10
inc(x)
However, it introduces function call overhead, so it's slower than typing x <- x + 1 yourself. If I'm not mistaken increment operator was introduced to make job for compiler easier, as it could convert the code to those machine language instructions directly.
R doesn't have these operations because (most) objects in R are immutable. They do not change. Typically, when it looks like you're modifying an object, you're actually modifying a copy.
Increment and decrement by 10.
require(Hmisc)
inc(x) <- 10
dec(x) <- 10
We released a package, roperators, to help with this kind of thing. You can read more about it here: https://happylittlescripts.blogspot.com/2018/09/make-your-r-code-nicer-with-roperators.html
install.packages('roperators')
require(roperators)
x <- 1:3
x %+=% 1; x
x %-=% 3; x
y <- c('a', 'b', 'c')
y %+=% 'text'; y
y %-=% 'text'; y
# etc
We can override +. If unary + is used and its argument is itself an unary + call, then increment the relevant object in the calling environment.
`+` <- function(e1,e2){
# if binary `+`, keep original behavior
if(!missing(e2)) return(base::`+`(e1, e2))
# if inner call isn't unary `+` called on language object,
# keep original behavior
inner_call <- substitute(e1)
inner_call_is_plus_on_lng <-
length(inner_call) == 2 &&
identical(inner_call[[1]], quote(`+`)) &&
is.language(inner_call[[2]])
if(!inner_call_is_plus_on_lng) return(base::`+`(e1))
eval.parent(substitute(X <- X + 1, list(X = inner_call[[2]])))
}
x <- 10
++x
x
#> [1] 11
other operations don't change :
x + 2
#> [1] 13
x ++ 2
#> [1] 13
+x
#> [1] 11
x
#> [1] 11
I can't really recommend it since you're messing with primitives which are optimised for a reason.
We can also use inplace
library(inplace)
x <- 1
x %+<-% 2
If you want to use i++ in an array to increment the index, you can try i <- i + 1, for example,
k = 0
a = 1:4
for (i in 1:4)
cat(a[k <- k + 1], " ")
# 1 2 3 4
but here <- can NOT be replaced with =, which does not update the index,
k = 0
a = 1:4
for (i in 1:4)
cat(a[k = k + 1], " ")
# 1 1 1 1
since = and <- are not always equivalent, as said in ?`<-`
Related
How (and can) I use different operators on command in if and else function?
x <- as.numeric(c(1,1,4,5,6,7,8))
if(mean(x) < 3){operator.is <- <}else{operator.is <- >}
sub <- subset(x, x operator.is 2)
#expected results
sub
[1] 3 4 5 6 7 8
I want to store the operator in "operator.is", based on the if statement. Yet, I do not seem to be able to store an operator and use it in the subset function. Later in want to use this operator to subset. Without this I will need to copy and past the whole code just to use the other operator. Is there any elegant and simple way to solve this?
Thanks in advance
operators can be assigned with the % sign:
`%op%` = `>`
vector <- c(1:10)
vector2 <- subset(vector, vector %op% 5)
In your case:
x <- as.numeric(c(1,1,4,5,6,7,8))
if(mean(x) < 3){`%operator.is%` <- `<`}else{`%operator.is%` <- `>`}
sub <- subset(x, x %operator.is% 2)
x <- as.numeric(c(1,1,4,5,6,7,8))
if(mean(x) < 3){`%my_op%` <- `<`}else{`%my_op%` <- `>`}
sub <- subset(x, x %my_op% 2)
sub
##[1] 4 5 6 7 8
"Things to remember while defining your own infix operators are that they must start and end with %. Surround it with back tick (`) in the function definition and escape any special symbols."
from https://www.datamentor.io/r-programming/infix-operator/
better to follow the lead of #Oliver and just
x <- as.numeric(c(1,1,4,5,6,7,8))
if(mean(x) < 3){operator.is <- `<`}else{operator.is <- `>`}
sub <- subset(x, operator.is(x,2))
sub
##[1] 4 5 6 7 8
I want to use env_get to evaluate a variable in the grandparent environment (I think) of the mutate call, but I couldn't manage. I'm describing a minimal example below.
Given a list like the following:
library(dplyr)
l <- list(X = 10,
df = tibble(n = seq(-10,10), y = rnorm(21), z = runif(21)))
And custom mutate for these lists.
mutate_.list <- function(.data, ...){
mutate_(.data$df, ...)
}
I want a function that can be run inside the mutate and can use the value of
X. Something like the following which doesn't work:
addX <- function(x) {
X <- rlang::env_get(env = parent.frame(2), 'X', inherit = TRUE)
x + X
}
This works as expected.
mutate(l, n + 1)
And I would like to be able to do this:
mutate(l, addX(n))
And this doesn't work. I guess I should go up parents somehow and be able to
refer to the list, but I couldn't manage. I tried to get the plausible names of the list arguments like this:
addX_test <- function(x) {
print(rlang::env_names(parent.frame(1)))
x
}
mutate(l, addX_test(n))
But I get stuff like the following:
[1] "~" ".top_env"
[3] ".__tidyeval_data_mask__." ".env"
Any pointers? Is it even doable?
Your X is a field inside l, so it's not directly visible in the corresponding environment. If you search for l instead, you can then access its fields.
addX( 1:3 ) # Error: object 'X' not found
addX_v2 <- function(x) {
ll <- rlang::env_get(env = parent.frame(2), 'l', inherit = TRUE)
x + ll$X
}
addX_v2( 1:3 )
# [1] 11 12 13
mutate( l, addX_v2(n) )
# # A tibble: 21 x 4
# n y z `addX_v2(n)`
# <int> <dbl> <dbl> <dbl>
# 1 -10 0.693 0.359 0
# 2 -9 -1.43 0.378 1
# 3 -8 -0.287 0.289 2
# 4 -7 -1.27 0.149 3
# ...
In general, it's not advisable to traverse the calling stack like that, because it breaks modularity of your code and introduces non-trivial dependencies that could lead to obscure bugs. In my opinion, a better approach is to use a function generator (function that returns a function), which will effectively bind the value of X to the computation that uses it:
Xadder <- function( .list ) { function(x) {x + .list$X} }
addX_v3 <- Xadder( l )
addX_v3(1:3)
# [1] 11 12 13
mutate( l, addX_v3(n) ) # Works as expected
Note that this version is more robust to a name change for your list, because it no longer searches for l directly.
Is there some equivalent to express let expressions in r? As an example take this simple haskell code:
let x = 1 in x + 1
Many thanks in advance.
One equivalent would be a lambda function, which you can define and call in a single statement:
(function(x) x+1)(x = 1)
The first () part defines a function, while the second () part calls that function, supplying the value of 1 for the argument named x.
Here are a few:
x <- 100
# 1
with(list(x = 1), x + 1)
## [1] 2
# 2
local(x + 1, list(x = 1))
## [1] 2
# 2a
local({
x <- 1
x + 1
})
## [1] 2
# 3
eval(substitute(x + 1, list(x = 1)))
## [1] 2
# 4
library(wrapr)
let(c(x = "1"),
x + 1,
subsMethod = "stringsubs",
strict = FALSE)
## [1] 2
x
## [1] 100
Also there is an open issue in the lambda.r package to add let.
If the intent of this is to make x only available in that expression, environments could offer this capability:
#make an environment
myenv <- new.env()
#assign 1 to variable x in our environment
myenv$x <- 1
#evaluate the expression within our environment
with(myenv, x + 1)
#[1] 2
#x only works within our created environment and not on the global environment
#(i.e. the default environment when working on the console)
x + 1
#Error: object 'x' not found
As per #Roland 's comment this can be shortened to local({x <- 1; x + 1}). See ?local.
One equivalent is a lambda function, whereby, you use the
implicit local({ }) within the function body
(this is a slightly improved answer of #ArtemSokolov's answer).
(function() {
x <- 1
x + 1
})()
This is equivalent to
local({
x <- 1
x + 1
})
I am looking for an efficient way to nest the same function in R until a condition is met. I hope the following example illustrates my problem clearly.
Consider the function
f(x) = x^2 + 1, with x > 1.
Denote
f^{(k)}(x) = f(f(f(...f(x)))),
where the function f is evaluated k times within itself. Let M > 0, with M given.
Is there any efficient routine in R to determine the minimum value of k such that f^{(k)}(2) > M?
Thank you.
Nothing special for that. Just use a loop:
function(x, M) {
k <- 0
repeat {
x <- x^2 + 1
k <- k + 1
if (x > M)
break
}
k
}
Not particularly efficient, but often the overhead of evaluating f will be greater than the overhead of the loop. If that's not the case (and it might not be for this particular f), I'd suggest doing the equivalent thing in C or C++ (perhaps using Rcpp).
This would be the recursive approach:
# 2^2 + 1 == 5
# 5^2 + 1 == 26
# 26^2 + 1 == 677
f <- function(x,M,k=0){
if(x <= M) k <- f(x^2 + 1,M=M,k+1)
return(k)
}
f(2,3) # 1
f(2,10) # 2
f(2,50) # 3
f(2,700) # 4
I am trying to create a loop in R that allows me to change the value of an object within the loop.
Below is an easy example to point out what exactly I mean by this. Print(x) stands for a rather extensive bulk of code, in which the value of x is needed for certain computations. However, while solution #1 works on paper, it is not usable in this context (because of sub loops). Is there any way to design a loop in R that resembles solution #2? Thanks a lot in advance!
1> x <- 1
2> while (x == 1)
3> {
4> print(x)
5> x <- 2
6> print(x)
7> x <- 3
8> print(x)
9> x <- 4
10> print(x)
11> if (x == 4)
12> break
13> }
Output
1
2
3
4
1> x <- 1
2> while (x == 1 || x == 2 || x == 3 || x == 4)
3> {
4> print (x)
5> x <- 2
#jump to line 2, ignore line 5, proceed with line 6
6> x <- 3
#jump to line 2, ignore line 6, proceed with line 7
7> x <- 4
#jump to line 2, ignore line 7, proceed with line 8
8> if (x == 4)
9> break
10> }
Output
1
2
3
4
It is somewhat hard to tell what exactly you want to do, but I'll give a shot, too. So you first might want to write a function that takes the value of x and does computations depending on the value of x (as far as I got it from your example, the computations/loops are not the same for all x).
x <- 1:4
fct <- function(x) {
if (x==1){
y <- x^2
}
if (x==2) {
y <- x + 2
}
if (x>2 & x < 5) {
y <- x*3 + 4
}
return(y)
}
Now loop over x:
sapply(x, fct)
Is that what you want?
I'm not sure it's gonna work because it's not clear exactly what you want to do, but could you try to put in a vector all the values you want to run print on? Like this:
my_values <- c(1,2,3,4)
for(x in my_values) {
print(x)
}
EDIT:
What I am gonna may be totally useless, but are you getting your next key from RODBC as well? If that's the case, suppose that you can get your next key with a function get_next_key and your data with get_data. I also assume that get_next_key returns NA if there is no more key (i.e you had the last key before). Would that work:
x = 1
while(!is.na(get_next_key(x))) {
data = get_data(x)
print(data)
x = get_next_key(x)
}
This first obviously works only for integer increments of x:
x <- 1
while (x <= 4){
print(x)
x <- x+1
}
For arbitrary values of x:
x1 <- c(1, 2, 3, 4)
### index x1 and move along this;
### at each step assign the value to y1 then
### do something with (print) it
for (i in seq_along(x1)) print(y1 <- x1[i])
Nothing really wrong with a for loop here and sometimes easier to read than apply