R: Printing Every 5th Output of a Loop - r

I am working with the R programming language.
I have this loop:
for (i in 1:100)
{
num_i = as.integer(rnorm(1,100,100))
print(num_i)
}
[1] 44
[1] -3
[1] -55
[1] 127
[1] 149
[1] 83
[1] 151
[1] 52
[1] 120
[1] 102
[1] 132
[1] 352
[1] 96
[1] 208
[1] 268
[1] 156
[1] 51
[1] 23
[1] 27
I only want to print every 5th output of this loop (i.e. 5th output, 10th output, 15th output, etc.):
[1] 83
[1] 132
[1] 156
I had an idea - I could use the concept of "modulo" in such a way, such that only every 5th output is printed. For example:
for (i in 1:100)
{
num_i = as.integer(rnorm(1,100,100))
ifelse(i %% 5 == 0, print(num_i), "" )
}
Have I done this correctly?
Thanks!

There are non-loop ways to do this to get the same output since rnorm can generate more than 1 number.
However, this seems to be a simplified example of what you are doing so in this case, you can continue the for loop using if/else -
for (i in 1:100) {
num_i = as.integer(rnorm(1,100,100))
if(i %% 5 == 0) {
print(num_i)
}
}
This will print nothing when the condition i %% 5 is FALSE. If you want it to print "" you may include the else condition.
Or since we are not using num_i when the condition is not satisfied so in this case we can generate the number only when i %% 5 == 0
for (i in 1:100) {
if(i %% 5 == 0) {
num_i = as.integer(rnorm(1,100,100))
print(num_i)
}
}

Related

Twin primes less than 87 in R

I am trying to list the first 87 twin primes. I'm using the Eratosthenes approach. Here is what I've worked on so far
Eratosthenes <- function(n) {
# Return all prime numbers up to n (based on the sieve of Eratosthenes)
if (n >= 2) {
sieve <- seq(2, n) # initialize sieve
primes <- c() # initialize primes vector
for (i in seq(2, n)) {
if (any(sieve == i)) { # check if i is in the sieve
primes <- c(primes, i) # if so, add i to primes
sieve <- sieve[(sieve %% i) != 0] # remove multiples of i from sieve
}
}
return(primes)
} else {
stop("Input value of n should be at least 2.")
}
}
Era <- c(Eratosthenes(87))
i <- 2:86
for (i in Era){
if (Era[i]+2 == Era[i+1]){
print(c(Era[i], Era[i+1]))
}
}
First thing I dont understand is this error:
Error in if (Era[i] + 2 == Era[i + 1]) { :
missing value where TRUE/FALSE needed
Second thing is in the list there are missing twin primes so for example (29,31)
Within your for loop, i is not index any more but the element in Era. In this case, you can try using (i+2) %in% Era to judge if i+2 is the twin
for (i in Era){
if ((i+2) %in% Era){
print(c(i,i+2))
}
}
which gives
[1] 3 5
[1] 5 7
[1] 11 13
[1] 17 19
[1] 29 31
[1] 41 43
[1] 59 61
[1] 71 73
A simpler way might be using diff, e.g.,
i <- Era[c(diff(Era)==2,FALSE)]
print(cbind(i,j = i+2))
which gives
> print(cbind(i,j = i+2))
i j
[1,] 3 5
[2,] 5 7
[3,] 11 13
[4,] 17 19
[5,] 29 31
[6,] 41 43
[7,] 59 61
[8,] 71 73
Firstly, (23,29) is not twin prime.
Secondly, your answer may be found in here
Edit: I've tried your code, I found that length of Era is 23.
Maybe when running if (Era[i] + 2 == Era[i+1]), it reaches to 24 and causes the problem.
for (i in Era) will set i to 2, then 3, then 5 etc which is not what you intended. Use for (i in seq_len(length(Era) - 1)).
for (i in seq_len(length(Era) - 1)){
if (Era[i] + 2 == Era[i + 1]){
print(c(Era[i], Era[i + 1]))
}
}
#> [1] 3 5
#> [1] 5 7
#> [1] 11 13
#> [1] 17 19
#> [1] 29 31
#> [1] 41 43
#> [1] 59 61
#> [1] 71 73

Modifying for loop with if conditions to apply format in R

I am creating a variable called indexPoints that contains a subset of index values that passed certain conditions -
set.seed(1)
x = abs(rnorm(100,1))
y = abs(rnorm(100,1))
threshFC = 0.5
indexPoints=c()
seqVec = seq(1, length(x))
for (i in seq_along(seqVec)){
fract = x[i]/y[I]
fract[1] = NaN
if (!is.nan(fract)){
if(fract > (threshFC + 1) || fract < (1/(threshFC+1))){
indexPoints = c(indexPoints, i)
}
}
}
I am trying to recreate indexPoints using a more efficient method like apply methods (any except sapply). I started the process as shown below -
set.seed(1)
x = abs(rnorm(100,1))
y = abs(rnorm(100,1))
threshFC = 0.5
seqVec <- seq_along(x)
fract = x[seqVec]/y[seqVec]
fract[1] = NaN
vapply(fract, function(i){
if (!is.nan(fract)){ if(fract > (threshFC + 1) || fract < (1/(threshFC+1))){ i}}
}, character(1))
However, this attempt causes an ERROR:
Error in vapply(fract, function(i) { : values must be length 1,
but FUN(X[[1]]) result is length 0
How can I continue to modify the code to make it in an apply format. Note: sometimes, the fract variable contains NaN values, which I mimicked for the minimum examples above by using "fract[1] = NaN".
There are several problems with your code:
You tell vapply that you expect the internal code to return a character, yet the only thing you ever return is i which is numeric;
You only explicitly return something when all conditions are met, which means if the conditions are not all good, you do not return anything ... this is the same as return(NULL) which is also not character (try vapply(1:2, function(a) return(NULL), character(1)));
You explicitly set fract[1] = NaN and then test !is.nan(fract), so you will never get anything; and
(Likely a typo) You reference y[I] (capital "i") which is an error unless I is defined somewhere (which is no longer a syntax error but is now a logical error).
If I fix the code (remove NaN assignment) in your for loop, I get
indexPoints
# [1] 3 4 5 6 10 11 12 13 14 15 16 18 20 21 25 26 28 29 30 31 32 34 35 38 39
# [26] 40 42 43 44 45 47 48 49 50 52 53 54 55 56 57 58 59 60 61 64 66 68 70 71 72
# [51] 74 75 77 78 79 80 81 82 83 86 88 89 90 91 92 93 95 96 97 98 99
If we really want to do this one at a time (I recommend against it, read below), then there are a few methods:
Use Filter to only return the indices where the condition is true:
indexPoints2 <- Filter(function(i) {
fract <- x[i] / y[i]
!is.nan(fract) && (fract > (threshFC+1) | fract < (1/(threshFC+1)))
}, seq_along(seqVec))
identical(indexPoints, indexPoints2)
# [1] TRUE
Use vapply correctly, returning an integer either way:
indexPoints3 <- vapply(seq_along(seqVec), function(i) {
fract <- x[i] / y[i]
if (!is.nan(fract) && (fract > (threshFC+1) | fract < (1/(threshFC+1)))) i else NA_integer_
}, integer(1))
str(indexPoints3)
# int [1:100] NA NA 3 4 5 6 NA NA NA 10 ...
indexPoints3 <- indexPoints3[!is.na(indexPoints3)]
identical(indexPoints, indexPoints3)
# [1] TRUE
(Notice the explicit return of a specific type of NA, that is NA_integer_, so that vapply is happy.)
We can instead just return the logical if the index matches the conditions:
logicalPoints4 <- vapply(seq_along(seqVec), function(i) {
fract <- x[i] / y[i]
!is.nan(fract) && (fract > (threshFC+1) | fract < (1/(threshFC+1)))
}, logical(1))
head(logicalPoints4)
# [1] FALSE FALSE TRUE TRUE TRUE TRUE
identical(indexPoints, which(logicalPoints4))
# [1] TRUE
But really, there is absolutely no need to use vapply or any of the apply functions, since this can be easily (and much more efficiently) checked as a vector:
fract <- x/y # all at once
indexPoints5 <- which(!is.nan(fract) & (fract > (threshFC+1) | fract < (1/(threshFC+1))))
identical(indexPoints, indexPoints5)
# [1] TRUE
(If you don't use which, you'll see that it gives you a logical vector indicating if the conditions are met, similar to bullet 3 above with logicalPoints4.)

Return list of lists from foreach loop in R

I have a function which returns a list of two objects (a list l and a number n). I want to loop over this function in a foreach loop.
create_lists <- function(){
l = sample(100, 5)
n = sample(100, 1)
return(list(l=l, n=n))}
Because create_lists has a list as ouput, this post told me to use a combine function which looks like this:
combine_custom <- function(list1, list2){
ls = c(list1$l, list2$l)
ns = c(list1$n, list2$n)
return(list(l = ls, n = ns))
}
So now my foreach loop looks like this:
m = foreach(i=1:5, .combine = combine_custom)%do%{
create_lists()}
My desired output would be:
m$l
[[1]]
[1] 100 25 86 21 28
[[2]]
[1] 78 37 79 41 61
[[3]]
[1] 73 22 78 94 13
[[4]]
[1] 15 28 76 78 52
[[5]]
[1] 32 93 92 2 1
m$n
[1] 52 56 3 79 82
But what I get is something like this:
$l
[1] 84 28 75 59 68 84 28 75 59 68
$n
[1] 31 91 18 98 39
So I have two problems:
1) Why is everything but two of the l lists dropped?
2) How can I make m$l to be a list of lists?
EDIT:
I tried another approach I got from here which does not use c:
combine_custom <- function(list1, list2){
ls = list1$l[[length(list1$l)+1]] = list(list2$l)
ns = c(list1$n, list2$n)
return(list(l = ls, n = ns))
}
But this gave the same result as described above, to be exact:
$l
$l[[1]]
[1] 65 84 48 81 82
$n
[1] 88 79 92 36 71
I have found another way which avoids the problem mentioned above, namely that combine has to create a new list first and later only append lists.
Also, the real function I am using actually returns a list of lists, so the following proved useful:
combine_custom <- function(list1, list2) {
if (plotrix::listDepth(list1$l) > plotrix::listDepth(list2$l)) {
ls <- c(list1$l, list(list2$l))
} else {
ls <- c(list(list1$l), list(list2$l))
}
ns <- c(list1$n, list2$n)
return(list(l = ls, n = ns))
}
This is not perfect if the function can return lists of varying nesting depths, but it works in my case.
The combine part is giving a lot of trouble, because on the first iteration, it needs to make a list out of two lists , but on the second iteration, it needs to append one list as an element to a list of lists.
Another approach (may or may not work depending on the size of your actual data/problem) is to use the purrr package for working with lists:
> m <- foreach(i=1:3)%do%{create_lists()}
> m
[[1]]
[[1]]$l
[1] 21 33 12 50 36
[[1]]$n
[1] 74
[[2]]
[[2]]$l
[1] 12 80 39 78 6
[[2]]$n
[1] 74
[[3]]
[[3]]$l
[1] 9 61 75 63 94
[[3]]$n
[1] 2
> purrr::transpose(m)
$l
$l[[1]]
[1] 21 33 12 50 36
$l[[2]]
[1] 12 80 39 78 6
$l[[3]]
[1] 9 61 75 63 94
$n
$n[[1]]
[1] 74
$n[[2]]
[1] 74
$n[[3]]
[1] 2
Hope that helps!
Thank you #Maria H., you solved my problem! The 'plotrix' package didn't work for me, but I used 'collapse' and it worked fine:
combine_custom1 <- function(a, b) {
if (collapse::ldepth(a) > collapse::ldepth(b)) {
ls <- c(a, list(b))
} else {
ls <- c(list(a), list(b))
}
return(ls)
}

Using While Function in a Fibonacci Sequence in R

I've written down a fibonacci code but I cant quite get the While function. Lets say I've made the sequence go up to 34 calculations, but I only want the results that are 4,000,000 or less. Here is the code that I have (bottom one is just to get prime numbers).
#rm (list=ls())
len <- 34
fibvals <- numeric(len)
fibvals[1] <- 1
fibvals[2] <- 1
for (i in 3:len) {
fibvals[i] <- fibvals[i-1]+fibvals[i-2]
}
fib.mat <- as.matrix(fibvals)
fib.mat[lapply(fib.mat, "%%", 2) == 0]
sum (fib.mat)
···········
Ive tried using codes such as this which either it goes on an infinite loop or just get an error. Any help would be appreciated, thanks!
while (fibvals < 4000000) {
print(fibvals)
}
It does not loop over the values of fibvals the way you coded it (you pass a vector of TRUE/FALSE values to while). You cold for example use an auxiliary counter variable like this:
counter <- 1
while (fibvals[counter] < 4000000) {
print(fibvals[counter])
counter <- counter + 1
}
This gives the desired result as I understood it.
You can do the following (note this takes around ~45 seconds on my laptop):
# Fibonacci numbers using recursive relation
fib <- function(n) {
val <- n;
if (n > 1) val <- fib(n - 1) + fib(n - 2);
return(val);
}
# Print Fibonacci numbers while < 4,000,0000
n <- 0;
while (fib(n) < 4000000) {
print(fib(n));
n <- n + 1;
}
#[1] 0
#[1] 1
#[1] 1
#[1] 2
#[1] 3
#[1] 5
#[1] 8
#[1] 13
#[1] 21
#[1] 34
#[1] 55
#[1] 89
#[1] 144
#[1] 233
#[1] 377
#[1] 610
#[1] 987
#[1] 1597
#[1] 2584
#[1] 4181
#[1] 6765
#[1] 10946
#[1] 17711
#[1] 28657
#[1] 46368
#[1] 75025
#[1] 121393
#[1] 196418
#[1] 317811
#[1] 514229
#[1] 832040
#[1] 1346269
#[1] 2178309
#[1] 3524578
you can use the explicit form of the Fibonacci sequence
fibonacciR <- function(n){(((1+sqrt(5))/2)^(n)-(1-((1+sqrt(5))/2))^(n))/sqrt(5)}
#fibonacciR(0:30)
result<-n<-0
while(fibonacciR(n)<4000000){
result<-c(result,fibonacciR(n));
n<-n+1}
result[-1]
[1] 0 1 1 2 3 5 8 13 21 34 55 89 144
[14] 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025
[27] 121393 196418 317811 514229 832040 1346269 2178309 3524578
It's very fast, it takes less than a second on my PC

R While loop exiting in the middle of loop

I'm trying to make a program that determines if a number is in a cluster based on a threshold. I need it to go through this while loop enough times to check all numbers and exit when only numbers not in the threshold are left. I've been using Boolean values to determine this. However, it seems to be that as soon as it's false the while loop stops.
Here's the while loop:
while(allInCluster){
centroid <- mean(cluster)
distance <- max(data)
data <- c(newData)
newData <- c()
smallest <- data[1]
allInCluster2 <- FALSE
for(i in 2:length(data)){
if((abs(centroid - data[i]) > distance) & (abs(centroid - data[i]) <= centroidThreshold)){
print("smallest")
print(smallest)
newData <- c(newData, smallest)
smallest <- data[i]
print("smallest changed")
print(smallest)
allInCluster2 <- TRUE
}else{
newData <- c(newData, data[i])
allInCluster2 <- FALSE
}
}
if(allInCluster2 == FALSE){
allInCluster <- FALSE
}
cluster <- c(cluster, smallest)
print("centroid")
print(centroid)
print("cluster")
print(cluster)
print("The other numbers")
print(newData)
}
Here's the sample data set I've been using:
data <- c(103,103,103,104,102, 102,102, 102,105,103, 110, 111)
with the threshold set to 5.
This is what it outputs:
[1] "cluster"
[1] 102 102 102 102
[1] "The other data"
[1] 103 103 103 104 105 103 110 111
[1] "centroid"
[1] 102
[1] "cluster"
[1] 102 102 102 102 103
[1] "The other numbers"
[1] 103 103 104 105 103 110 111
>

Resources