Adding a counter to a loop - r

On a broad question that I haven't been able to find for R:
I'm trying to add a counter at the beginning of a loop.
So that when I run the loop sim = 1000:
if(hours$week1 > 1 and hours$week1 < 48) add 1 to the counter
ifelse add 0
I have came across counter tutorials that print a sentence to let you know where you are (if something goes wrong):
e.g
For (i in 1:1000) {
if (i%%100==0) print(paste("No work", i))
}
But the purpose of my counter is to generate a value output, measuring how many of the 1000 runs in the loop fall inside a specified range.

You basically had it. You just need to a) initialize the counter before the loop, b) use & instead of and in your if condition, c) actually add 1 to the counter. Since adding 0 is the same as doing nothing, you don't have to worry about the "else".
counter = 0
for (blah in your_loop_definition) {
... loop code ...
if(hours$week1 > 1 & hours$week1 < 48) {
counter = counter + 1
}
... more loop code ...
}

Instead of
if(hours$week1 > 1 & hours$week1 < 48) {
counter = counter + 1
}
you could also use
counter = counter + (hours$week1 > 1 && hours$week1 < 48)
since R is converting TRUE to 1 and FALSE to 0.

How about this?
count = 0
for (i in 1:1000) {
count = ifelse(i %in% 1:100, count + 1, count)
}
count
#> [1] 100

If your goal is just to monitor progression coarsely, and you're using Rstudio, a simple solution is to just refresh the environment tab to check the current value of i.

Related

I want to calculate the timedifference between to times

I want to calculate the difference of two columns of a dataframe containing times. Since not always a value from the same column ist bigger/later, I have to do a workaround with an if-clause:
counter = 1
while(counter <= nrow(data)){
if(data$time_end[counter] - data$time_begin[counter] < 0){
data$chargingDuration[counter] = 1-abs(data$time_end[counter]-data$time_begin[counter])
}
if(data$time_end[counter] - data$time_begin[counter] > 0){
data$chargingDuration[counter] = data$time_end[counter]-data$time_begin[counter]
}
counter = counter + 1
}
The output I get is a decimalvalue smaller than 1 (i.e.: 0,53322 meaning half a day)... However, if I use my console and calculate the timedifference manually for a single line, I get my desired result looking like 02:12:03...
Thanks for the help guys :)

When running code in R was given an error that there was a missing value where true/false needed and I can't fix it

I am new to using R and have minimal amount of Python experience. I am sure this is an easy fix but I am just not seeing it. I was given a code to run a Fibonacci sequence to 100 and I copy and pasted it, but I am getting the following error code: Error in if (numterms <= 0) { : missing value where TRUE/FALSE needed. I know this has to do with the if/else clause but I am not seeing the problem.
I have run through the code a couple different ways but it has not helped. And the person to assist is not available during the weekend. Any help would be appreciated.
# take the max number input from the user
numterms = as.integer(readline(prompt="What is your max number? "))
# first two items
num1 = 0
num2 = 1
counter = 2
# check if the number of terms is valid
if(numterms <= 0) {
print("Please enter an integer above zero")
} else {
if(numterms == 1) {
print("The Fibonacci sequence:")
print(num1)
} else {
print("The Fibonacci sequence:")
print(num1)
print(num2)
while(counter < numterms) {
numth = num1 + num2
print(numth)
# update values
num1 = num2
num2 = numth
counter = counter + 1
}
}
}
If you just execute the code numterms is not correctly defined. It is normally defined by a user input: The function readline reads the numbers the user types in the command line. If you just execute this line you can properly define numterms.
If you execute all the code at once numterms is set to NA which cannot be compared to 0 in the numterms <= 0 clause. In this case numterms <= 0 is also NA which is not a logical value and can therefore not be evaluated by if. This ultimately causes your error.
The solution would be to just run the first line of your code and enter the number and only after you entered the number to execute the rest of the code.
Alternatively you can define your code as a function:
printFibonacci <- function(){
numterms = as.integer(readline(prompt="What is your max number? "))
if(is.na(numterms)){
numterms <- 4
}
# first two items
num1 = 0
num2 = 1
counter = 2
# check if the number of terms is valid
if(numterms <= 0) {
print("Please enter an integer above zero")
} else {
if(numterms == 1) {
print("The Fibonacci sequence:")
print(num1)
} else {
print("The Fibonacci sequence:")
print(num1)
print(num2)
while(counter < numterms) {
numth = num1 + num2
print(numth)
# update values
num1 = num2
num2 = numth
counter = counter + 1
}
}
}
}
And then just call your function with printFibonacci(). In this case the prompt and answer of the readline function gets executed first and numterms can be defined by the user before the rest of the code is executed.

translate correctly `for(int i = 1; i <= size; i++)` in R (case `size < 1`)

I used to write for loops in R like
for(i in 1:size) { ... }
and I thought that it was equivalent of
for(int i = 1; i <= size; i++) { ... }
but I just realised that if size == 0 R enters the loop anyway because 1:size = [1 0] and so my code behaves totally wrong.
So, what is the real standard way of translating the C for loop I wrote above, such that if size < 1 the program does not enter the loop?
Assuming that size is some size of your object, e.g. length(vec) or nrow(df), you can use seq_along like below:
x = NULL
for (i in seq_along(x)) print(x[i])
If size is originally the length of a vector, the standard way is
for (i in seq_along(myvector)) {...}
which will behave correctly if myvector has length zero. So you could even do
for (i in seq_along(numeric(size))) {...}
but that would be certainly not be considered "standard".
As noted in the comments (and in another answer) the better way is
for (i in seq_len(size)) {...}
You can use base::seq_len:
foo <- 2
bar <- 0
for (i in seq_len(foo)) {print(i)}
[1] 1
[1] 2
# No output
for (i in seq_len(bar)) {print(i)}

R while loop and number of times

got a while loop going, and that's working fine.
However I also need to add another condition.
I need the loop to keep going until it satisfies the while loop, but then I also need to add that this can only get repeated x times.
I think you would have to make a for loop to do x times, is it possible to put a while loop in this?
Basically how can I make a loop either reach the goal or stop after x loops??
The expression in while needs to be TRUE for the loop to continue. You can use | or & to add extra conditions. This loop runs 99 times or until sum of random variables is less than 100.
counter <- 0
result <- 0
while(counter < 100 | sum(result) < 100) {
result <- sum(result, rnorm(1, mean = 5, sd = 1))
counter <- sum(counter, 1)
}
> result
[1] 101.5264
> counter
[1] 21
Just pass the current iterator value as an argument to your function. That way you can break the recursion if that reaches a particular value.
But why do you have a while loop if you use recursion, for example:
add_one_recursive = function(number) {
number = number + 1
cat("New number = ", number, "\n")
if(number > 10) {
return(number)
} else {
return(add_one_recursive(number))
}
}
final_number = add_one_recursive(0)
New number = 1
New number = 2
New number = 3
New number = 4
New number = 5
New number = 6
New number = 7
New number = 8
New number = 9
New number = 10
New number = 11
Does not require an explicit loop at all.

R - vectorised conditional replace

Hi I'm trying manipulate a list of numbers and I would like to do so without a for loop, using fast native operation in R. The pseudocode for the manipulation is :
By default the starting total is 100 (for every block within zeros)
From the first zero to next zero, the moment the cumulative total falls by more than 2% replace all subsequent numbers with zero.
Do this far all blocks of numbers within zeros
The cumulative sums resets to 100 every time
For example if following were my data :
d <- c(0,0,0,1,3,4,5,-1,2,3,-5,8,0,0,-2,-3,3,5,0,0,0,-1,-1,-1,-1);
Results would be :
0 0 0 1 3 4 5 -1 2 3 -5 0 0 0 -2 -3 0 0 0 0 0 -1 -1 -1 0
Currently I have an implementation with a for loop, but since my vector is really long, the performance is terrible.
Thanks in advance.
Here is a running sample code :
d <- c(0,0,0,1,3,4,5,-1,2,3,-5,8,0,0,-2,-3,3,5,0,0,0,-1,-1,-1,-1);
ans <- d;
running_total <- 100;
count <- 1;
max <- 100;
toggle <- FALSE;
processing <- FALSE;
for(i in d){
if( i != 0 ){
processing <- TRUE;
if(toggle == TRUE){
ans[count] = 0;
}
else{
running_total = running_total + i;
if( running_total > max ){ max = running_total;}
else if ( 0.98*max > running_total){
toggle <- TRUE;
}
}
}
if( i == 0 && processing == TRUE )
{
running_total = 100;
max = 100;
toggle <- FALSE;
}
count <- count + 1;
}
cat(ans)
I am not sure how to translate your loop into vectorized operations. However, there are two fairly easy options for large performance improvements. The first is to simply put your loop into an R function, and use the compiler package to precompile it. The second slightly more complicated option is to translate your R loop into a c++ loop and use the Rcpp package to link it to an R function. Then you call an R function that passes it to c++ code which is fast. I show both these options and timings. I do want to gratefully acknowledge the help of Alexandre Bujard from the Rcpp listserv, who helped me with a pointer issue I did not understand.
First, here is your R loop as a function, foo.r.
## Your R loop as a function
foo.r <- function(d) {
ans <- d
running_total <- 100
count <- 1
max <- 100
toggle <- FALSE
processing <- FALSE
for(i in d){
if(i != 0 ){
processing <- TRUE
if(toggle == TRUE){
ans[count] <- 0
} else {
running_total = running_total + i;
if (running_total > max) {
max <- running_total
} else if (0.98*max > running_total) {
toggle <- TRUE
}
}
}
if(i == 0 && processing == TRUE) {
running_total <- 100
max <- 100
toggle <- FALSE
}
count <- count + 1
}
return(ans)
}
Now we can load the compiler package and compile the function and call it foo.rcomp.
## load compiler package and compile your R loop
require(compiler)
foo.rcomp <- cmpfun(foo.r)
That is all it takes for the compilation route. It is all R and obviously very easy. Now for the c++ approach, we use the Rcpp package as well as the inline package which allows us to "inline" the c++ code. That is, we do not have to make a source file and compile it, we just include it in the R code and the compilation is handled for us.
## load Rcpp package and inline for ease of linking
require(Rcpp)
require(inline)
## Rcpp version
src <- '
const NumericVector xx(x);
int n = xx.size();
NumericVector res = clone(xx);
int toggle = 0;
int processing = 0;
int tot = 100;
int max = 100;
typedef NumericVector::iterator vec_iterator;
vec_iterator ixx = xx.begin();
vec_iterator ires = res.begin();
for (int i = 0; i < n; i++) {
if (ixx[i] != 0) {
processing = 1;
if (toggle == 1) {
ires[i] = 0;
} else {
tot += ixx[i];
if (tot > max) {
max = tot;
} else if (.98 * max > tot) {
toggle = 1;
}
}
}
if (ixx[i] == 0 && processing == 1) {
tot = 100;
max = 100;
toggle = 0;
}
}
return res;
'
foo.rcpp <- cxxfunction(signature(x = "numeric"), src, plugin = "Rcpp")
Now we can test that we get the expected results:
## demonstrate equivalence
d <- c(0,0,0,1,3,4,5,-1,2,3,-5,8,0,0,-2,-3,3,5,0,0,0,-1,-1,-1,-1)
all.equal(foo.r(d), foo.rcpp(d))
Finally, create a much larger version of d by repeating it 10e4 times. Then we can run the three different functions, pure R code, compiled R code, and R function linked to c++ code.
## make larger vector to test performance
dbig <- rep(d, 10^5)
system.time(res.r <- foo.r(dbig))
system.time(res.rcomp <- foo.rcomp(dbig))
system.time(res.rcpp <- foo.rcpp(dbig))
Which on my system, gives:
> system.time(res.r <- foo.r(dbig))
user system elapsed
12.55 0.02 12.61
> system.time(res.rcomp <- foo.rcomp(dbig))
user system elapsed
2.17 0.01 2.19
> system.time(res.rcpp <- foo.rcpp(dbig))
user system elapsed
0.01 0.00 0.02
The compiled R code takes about 1/6 the time the uncompiled R code taking only 2 seconds to operate on the vector of 2.5 million. The c++ code is orders of magnitude faster even then the compiled R code requiring just .02 seconds to complete. Aside from the initial setup, the syntax for the basic loop is nearly identical in R and c++ so you do not even lose clarity. I suspect that even if parts or all of your loop could be vectorized in R, you would be sore pressed to beat the performance of the R function linked to c++. Lastly, just for proof:
> all.equal(res.r, res.rcomp)
[1] TRUE
> all.equal(res.r, res.rcpp)
[1] TRUE
The different functions return the same results.

Resources