If else statement comparing to 0 or NA - r

I have an element in a data frame tmp that may contain either a number, 0, or NA. If that element is neither 0 or NA, I would like something to happen. Otherwise, nothing happens. I imagine it'd look like this:
if ( tmp[2, 19] != (0 || NA) ){
do something
}
I get this error: Error in if (tmp[2, 19] == (0 || NA)) { : missing value where TRUE/FALSE needed. I don't know if it's not possible in R to compare something to both an int and a string or if I'm just using the OR operator wrong. I've tried different variations in different cases but haven't been able to determine the problem. Please help!

As #GSee said in a comment, you need to use is.na:
if(tmp[2, 19] != 0 || is.na(tmp[2, 19])) {
# do stuff
}
You could have discovered this yourself by reading ?"if" and ?NA.

Related

How to continue a while loop while the condition is false in r?

I have this while loop:
while (abs(B-left)<INFSMALL | abs(B-right)<INFSMALL) {
...
}
I want it to run while the above condition is FALSE. Is there an easy way to do this?
Use one of:
Negate the entire conditional by wrapping it with !(.), as in
while (!(abs(B-left) < INFSMALL || abs(B-right) < INFSMALL)) {
...
}
Negate the components inside, and change from OR to AND:
while (abs(B-left) >= INFSMALL && abs(B-right) >= INFSMALL) {
...
}
You should be using || instead of |, see Boolean operators && and ||. The flow-control functions if and while need the conditional to be length-1 exactly, not 0, no more than 1. While | will produce a vector of length 1 if all of the arguments are length 1, there are two reasons this is still a bad idea:
Short-circuiting: in general, if the first (of multiple, chained) conditional suggests that the second (and beyond) conditional does not matter, than short-circuiting means it will not evaluate them. Without predefining aa, for instance, compare
exists("aa") && aa > 0
# [1] FALSE
exists("aa") & aa > 0
# Error: object 'aa' not found
Declarative code: the control-flow while must only take length-1, make sure you know this going in. It's perhaps a little bit of style, so more-so #1 above.

Netsuite - Saved Search Formula(text) Case statement multiply 2 fields

I'm trying to get the product of 2 fields in the 'ELSE' portion of a CASE statement of a Formula(Text) row in a Netsuite saved search, but I keep getting 'ERROR: Invalid Expression' when I run the search. Current formula is:
CASE WHEN {binonhandcount} = 0 THEN '0' ELSE NVL({binonhandcount}, 0) * NVL({locationaveragecost}, 0) END
I've tried to simplify it by doing something like this:
CASE WHEN {binonhandcount} = 0 THEN '0' ELSE 1 + 1 END
But it still fails with an invalid expression error. All of the Googling I've done leads me to believe that this should work, but I can't seem to find my mistake. I'm hoping the extra eyes here can give me a kick in the right direction. Thank you.
The data type returned from the formula needs to match the Formula type selected. You can correct your formula by setting it to a Formula (Numeric) type and simply removing the quotes around the '0' after the first THEN:
CASE WHEN {binonhandcount} = 0 THEN 0 ELSE NVL({binonhandcount}, 0) * NVL({locationaveragecost}, 0) END
Or if you really want a text formula for some reason, you can wrap the ELSE statement in a TO_CHAR function:
CASE WHEN {binonhandcount} = 0 THEN '0' ELSE TO_CHAR(NVL({binonhandcount}, 0) * NVL({locationaveragecost}, 0)) END
In your NetSuite saved search replace Formula(text) to Formula(Numeric).
And your formula would be:
CASE WHEN {binonhandcount} = 0 THEN 0 ELSE NVL({binonhandcount}, 0) * NVL({locationaveragecost}, 0) END
Please remove the string from THEN '0'. You should be fine.

After checking condition need to add a column and assign a value

I have a data frame(final1) with few columns
for(i in final1$Total.Tyres)
{
if(final1$Total.Tyres[i] >= 500){
final1$flag_tyres[i]<-1
} else {
final1$flag_tyres[i]<-0
}
}
I need to check if tires are greater than 500 if so need to assign 1 adding a new column flag_tyres
when tried the above code give me below error
Error in if (final1$Total.Tyres[i] >= 500) { :
missing value where TRUE/FALSE needed
You may want to consider vectorizing your code instead of using for to loop over the rows, saves you typing, hassle and is faster:
final1$flag_tyres <- ifelse(final1$Total.Tyres >= 500, 1, 0)
Simple mistake, should be 1:length(final1$Total.Tyres) in the outer loop. Alternatively, you could vectorize the result, as already answered.

Can't understand the error message in the if condition in R

My program written in R sometimes (not always, but almost always when the simulation is run for a large number of times) shows this error message:
Error in if (sum.wt1y1 == 0 | sum.wt2y2 == 0) zn[k] <- 0 else zn[k] <- (sum.wt1y1 * :
missing value where TRUE/FALSE needed
Can anyone explain me what is the meaning of this error message? I cannot find where the error is. The final output is a vector. Now in that vector up to some values it shows "values" but the rest are 0, 0, 0,..., 0 when the error message appears. If the error message do not appear, then all the positions of the vector is filled up with values (no zeros).
The error arises due to NA values usually:
if (NA == 0) print('foo')
# Error in if (NA == 0) print("foo") :
# missing value where TRUE/FALSE needed
The solution is to remove missing values or include a check for them:
if (!is.na(x) & x == 0) ...
Try this:
which(is.na( sum.wt1y1 == 0 | sum.wt2y2 == 0))
To expand on what #justin said, the error message is essentially telling you that it was expecting a T/F but did not get it.
When you see such an error, the best thing to do is to explore the value that is inside
the parens in your if( .... ) statement.
In this specific case, looking at sum.wt1y1 == 0 | sum.wt2y2 == 0 would probably help you find the culprit.

Is there better syntax for simple if, assigning variable

I have code that basically assigns a variable in one case, else a different in another. Is there a neater way that is more efficient?
I.e., not taking up so many lines. Or is this the best way?
if (ViewBag.Date != RoomBooking.StartDateTime.Date || ViewBag.DayPlannerStartTime * 12 > (Int32)RoomBooking.StartDateTime.TimeOfDay.TotalMinutes / 5)
{
StartBlock = ViewBag.DayPlannerStartTime * 12;
}
else
{
StartBlock = ((Int32)RoomBooking.StartDateTime.TimeOfDay.TotalMinutes / 5);
}
Maybe this (it's arguably neater, but definitely has the same efficiency):
StartBlock = (ViewBag.Date != RoomBooking.StartDateTime.Date || ViewBag.DayPlannerStartTime * 12 > (Int32)RoomBooking.StartDateTime.TimeOfDay.TotalMinutes / 5)
? ViewBag.DayPlannerStartTime * 12
: ((Int32)RoomBooking.StartDateTime.TimeOfDay.TotalMinutes / 5);
EDIT: You can slightly optimize the condition as well. I suspect that your DayPlannerStartTime is expressed in seconds, and if I'm right you can rewrite the comparison the following way (I just divided both operands of the > operator by 12, and TotalMinutes divided by 5*12 became TotalHours):
ViewBag.DayPlannerStartTime > (Int32)RoomBooking.StartDateTime.TimeOfDay.TotalHours
Yes, you can use the ?: operator to create a single expression that will evaluate to the first expression if the condition is true, or else to the second expression:
// condition ? first_expression : second_expression;
var value = (something that is true or false) ? value if true : value if false;

Resources