This is a test version of Biostars. For the public version, visit https://www.biostars.org.
R loop not functional

I am writing an R-script to check for a particular expression value in a narrow range of values. For example, expression count of Gene A = 0.8. I want the flexibility to be 0.2, therefore if Gene X (the gene under test) = 0.5 to 1.1, I'll consider the expressions to be equal. The R-script I have written has an if-statement nested within a for-loop, and the loop is functioning at times, and sometimes it isn't.

I am pasting the script below to avoid any confusion -

a = 0.8
b= 0.68

a_vec = seq(a-0.3,a+0.3, by=0.001)

for(i in a_vec) {
    if(i == b) {
            print(b)
    }
}

When b = 0.68, 0.3, 0.35 there is no output, but when b = 0.8, 1, 1.1, 1.03 it prints 0.8, 1, 1.1, 1.03

r for-loop if-statement

Hi, one tip. If you want people to read your code, please make your code human readable. We are not machines.

I'm sorry, but what is the problem?

This looks more legible!

Nothing any more, I modified your post :)

Thanks for the modification, Devon :)

I am not sure I understand what you want to do. Is it "if your value(gene X) is comprised between value(gene A) +/- 0.3 you print something like 'TRUE' if not 'FALSE' " ?

If so it would be either to go for a statement like the following one: if(b < a+0.3 | b > a-0.3) print(TRUE) else { print(FALSE)}

I want the value printed, not TRUE or FALSE. I need to use these values further. I need the values printed mainly because I will have a huge collection, and need to know which are the ones present.

You'd be better using Filter() than trying to use print() - especially if you have a huge collection of things to check

If you're using for-loops in R, you're doing it wrong!

I disagree. I know that R fanatics want you to use the apply family of functions, but if R is not the only language you use, the for loop is the most important loop in bioinformatics.

2 answers

Welcome to the joys of floating point precision. In general, you should not check i == b, but rather abs(i-b) < 1e-6 or some other reasonable tolerance.

Is abs() for absolute? If yes, then I'll need something else, because I have negative counts too.

if ((abs(b-a)<=0.3)==T) {print (b)} # if script
ifelse ((abs(b-a)<=0.3),b,NA) # ifelse script
b[sapply(b, function(x) abs(x-a)<=0.3)] # sapply script
b[sapply((abs(b-a)<=0.3), isTRUE)] # sapply and istrue
b[(abs(b-a)<=0.3)] # shortening further

Code:

>a = 0.8
>b=c( 0.68, 0.3, 0.35, 0.8, 1, 1.1, 1.03 )
>ifelse((abs(b-a)<=0.3),as.numeric(b),NA)  # script 2
>b[sapply(b, function(x) abs(x-a)<=0.3)] # script 3
>b[(abs(b-a)<=0.3)]

Result

> ifelse((abs(b-a)<=0.3),as.numeric(b),NA)
[1] 0.68   NA   NA 0.80 1.00   NA 1.03

> b[sapply(b, function(x) abs(x-a)<=0.3)]
[1] 0.68 0.80 1.00 1.03

> b[sapply((abs(b-a)<=0.3), isTRUE)]
[1] 0.68 0.80 1.00 1.03

> b[(abs(b-a)<=0.3)]
[1] 0.68 0.80 1.00 1.03

Yes, abs() is the absolute value. In general, though, I would suggest that what cpad0112 showed is generally a more reasonable approach.

A solution to this in R is not to use ==, but rather the all.equal function. Since all.equal gives lots of detail about the differences if there are any, isTRUE(all.equal(...)).

a = 0.8
b = 0.68

a_vec = seq(a-0.3,a+0.3, by=0.001)

for(i in a_vec){
if(isTRUE(all.equal(i,0.68))) cat(b)  
}

+1 for isTRUE(), I too learned about that one the hard way

Log in to answer this question.