In R programming can we have if inside for loop - r

In R programming can we have if inside for loop
for(i in 1:length(abc)){
print(i)
if(){}
}
this code is giving error I don't know why

Empty conditions in if are not allowed:
> if(){}
Error: unexpected ')' in "if()"
Use TRUE if you want the block to always be executed, or FALSE if you never want it executed:
> if(TRUE){}
NULL
>
There's no problem with this in a loop.

Yes, for example you can have
for(i in 1:10){
if (i<5)
{print(i)}
else
{print(i+10)}
}
Which prints the following.
[1] 1
[1] 2
[1] 3
[1] 4
[1] 15
[1] 16
[1] 17
[1] 18
[1] 19
[1] 20

Related

Getting "argument is of length 0" inside if statement [duplicate]

I am having a little problem with R and I am not sure why. It is telling me that this line: if(temp > data[[k]][[k2]]) { is of argument length 0. Here is the block which is not that big:
for(k in 1:length(data)) {
temp <- 0
for(k2 in 3:length(data[[k]])) {
print(data[[k]][[k2]])
if(temp > data[[k]][[k2]]) {
temp <- data[[k]][[k2]]
}
fMax[k] <- temp
k2 <- k2 + 1
}
k <- k + 1
}
example of what is in data[[k]][[k2]]:
[1] "3050"
[1] "3051"
[1] "3054"
[1] "3054"
[1] "3052"
[1] "3053"
[1] "3059"
[1] "3059"
[1] "3057"
[1] "3060"
[1] "3063"
[1] "3060"
[1] "3068"
[1] "3067"
[1] "3079"
[1] "3085"
[1] "3094"
[1] "3107"
[1] "3121"
[1] "3135"
[1] "3147"
[1] "3161"
[1] "3200"
[1] "3237"
[1] "3264"
[1] "3274"
[1] "3284"
[1] "3289"
[1] "3292"
[1] "3300"
[1] "3301"
[1] "3303"
[1] "3306"
[1] "3310"
[1] "3312"
[1] "3313"
[1] "3319"
[1] "3314"
[1] "3318"
[1] "3318"
[1] "3320"
[1] "3322"
[1] "3322"
[1] "3322"
[1] "3328"
[1] "3332"
[1] "3338"
[1] "3350"
[1] "3358"
[1] "3378"
[1] "3395"
[1] "3402"
[1] "3875"
[1] "3950"
[1] "3988"
[1] "4018"
[1] "4039"
[1] "4048"
[1] "4057"
[1] "4062"
[1] "4067"
[1] "4076"
[1] "4082"
[1] "4085"
[1] "4092"
[1] "4098"
[1] "4099"
[1] "4101"
[1] "4107"
[1] "4119"
[1] "4139"
[1] "4164"
[1] "4231"
[1] "4347"
[1] "4559"
"argument is of length zero" is a very specific problem that comes from one of my least-liked elements of R. Let me demonstrate the problem:
> FALSE == "turnip"
[1] FALSE
> TRUE == "turnip"
[1] FALSE
> NA == "turnip"
[1] NA
> NULL == "turnip"
logical(0)
As you can see, comparisons to a NULL not only don't produce a boolean value, they don't produce a value at all - and control flows tend to expect that a check will produce some kind of output. When they produce a zero-length output... "argument is of length zero".
(I have a very long rant about why this infuriates me so much. It can wait.)
So, my question; what's the output of sum(is.null(data[[k]]))? If it's not 0, you have NULL values embedded in your dataset and will need to either remove the relevant rows, or change the check to
if(!is.null(data[[k]][[k2]]) & temp > data[[k]][[k2]]){
#do stuff
}
Hopefully that helps; it's hard to tell without the entire dataset. If it doesn't help, and the problem is not a NULL value getting in somewhere, I'm afraid I have no idea.
The same error message results not only for null but also for e.g. factor(0). In this case, the query must be if(length(element) > 0 & otherCondition) or better check both cases with if(!is.null(element) & length(element) > 0 & otherCondition).
You can use isTRUE for such cases. isTRUE is the same as { is.logical(x) && length(x) == 1 && !is.na(x) && x }
If you use shiny there you could use isTruthy which covers the following cases:
FALSE
NULL
""
An empty atomic vector
An atomic vector that contains only missing values
A logical vector that contains all FALSE or missing values
An object of class "try-error"
A value that represents an unclicked actionButton()
I spent an entire day bashing my head against this, the solution turned out to be simple..
R isn't zero-index.
Every programming language that I've used before has it's data start at 0, R starts at 1.
The result is an off-by-one error but in the opposite direction of the usual.
going out of bounds on a data structure returns null and comparing null in an if statement gives the argument is of length zero error. The confusion started because the dataset doesn't contain any null, and starting at position [0] like any other pgramming language turned out to be out of bounds.
Perhaps starting at 1 makes more sense to people with no programming experience (the target market for R?) but for a programmer is a real head scratcher if you're unaware of this.
The argument is of length zero takes places when you get an output as an integer of length 0 and not a NULL output.i.e.,
integer(0).
You can further verify my point by finding the class of your output-
>class(output)
"integer"
The simplest solution to the problem is to change your for loop statement :
Instead of using
for (i in **0**:n))
Use
for (i in **1**:n))
In my case, I just wanted to see the first position of the character as follows
htagPos <- which(strsplit(val, "")[[1]] == "#")
if(htagPos == 1){
next
}# this did now work:(
So I had to check the length of the result first before checking the value
htagPos <- which(strsplit(val, "")[[1]] == "#")
if(length(htagPos) >= 1 && htagPos == 1){
next
}
I see why most people prefer python...
So the other possibility for this error can be when the condition in IF is a return value from other function.
For example,
check <- function (value) {
if (value == 0) {
return TRUE
}
Now,
If this function is called like this:
if(check(value)) {
do something
}
So here, let's assume the value is not 0, there is no return statement for that case. In this case too, you'll get "argument is of length zero" error.
Hope this is helpful!
String data structures have the last data addressed nulled so use max(data) instead of data[last].
https://www.geeksforgeeks.org/string-data-structure/
For example,a string with 4 elements will have a number element in it's 5th element.

Returned an extra printed result "[1] 36" from for loop: How to remove it?

#Create a function to print squares of numbers in sequence
squareseq <- function(a) {
for(i in 1:a) {
b <- i^2
result <- print(b)
}
return(result)
}
# Call the function supplying 6 as an argument
squareseq(6)
The result of calling the function above, is shown below:
[1] 1
[1] 4
[1] 9
[1] 16
[1] 25
[1] 36
[1] 36
How do I keep "return(result)" but remove the duplicated line: "[1] 36"? So I get this result below:
[1] 1
[1] 4
[1] 9
[1] 16
[1] 25
[1] 36
Use invisible:
squareseq <- function(a) {
for(i in 1:a) {
b <- i^2
result <- print(b)
}
invisible(result)
}
squareseq(6)
#[1] 1
#[1] 4
#[1] 9
#[1] 16
#[1] 25
#[1] 36
My answer is going to be old fashion theortical here.
Problem in your approach is first you are printing values in for loop so whenever function is called it will print as per argument(all numbers). Now when function comes out of that loop you are returning the value which will return latest value of variable named result in your case, that is the actually reason only last item is being printed 2 times(because item is already printed previously and now getting returned).
As per #Roland's comments I have edited my answer now(where it was saying do not return anything in function, seems to be not applicable with R). Since it is mandatory to return a value in R so pleaseuse #DiceboyT's nice solution using invisible.

Why doesn't this function print to screen when called in a loop?

Can anyone help me understand this behavior?
test<-c(1,2,3,4)
adding<-function(file){
file2<- file + 1
return(file2)
}
yields upon calling:
> adding(file = 1)
[1] 2
but when I try:
for(number in test){
adding(number)
print(number)
}
I get:
> for(number in test){
+ adding(number)
+ print(number)
+ }
[1] 1
[1] 2
[1] 3
[1] 4
when I would've expected:
[1] 2
[1] 1
[1] 3
[1] 2
[1] 4
[1] 3
[1] 5
[1] 4
I'm using this basis for another for loop that I'm working on and wondering why it's not behaving as I expect.
Opt for
for(number in test){
print(adding(number))
print(number)
}
to have your expected behavior, else adding per se won't print to screen.
Your example works exactly as expected. You never explicitly printed the return value from the function call in the loop. Automatic printing is turned off in loops.
If you want the result of the function applied to each element of the vector as a vector itself, then
purrr::map_dbl(test, adding)
## [1] 2 3 4 5
or
sapply(test, adding)
Printing something to screen without a print statement only happens in an interactive environment and only if you are inside out most scopes. The variables inside the function have their own scope and those variables are not printed.
Food for though: This is for example different in MATLAB, where the result of every statement not ending with ; is printed. In Python an additional requirement is that such a statement is executed alone. So executing two statements will not print anything, even if the last one is something that might be printed.

apply function - custom function returning NULL at the end

x = matrix(1:5)
func = function(x) {
for ( i in 1:x ) {
print(i)
}
}
apply(X=x, 1, func)
Output :
[1] 1
[1] 1
[1] 2
[1] 1
[1] 2
[1] 3
[1] 1
[1] 2
[1] 3
[1] 4
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
NULL
Why is this function generating NULL at the end ?
By definition, an R function returns the result of the last expression to be evaluated. In this case, the expression is the entire for loop, which returns NULL. If you want to not print the null result, you can store the result in a variable (result <- apply(...)) or use invisible():
invisible(apply(X=x, 1, func))
I don't know of a way to modify the function itself to get this behaviour, since you are calling the function through apply().
By the way, why not invisible(lapply(x,func)) ?

Argument is of length zero in if statement

I am having a little problem with R and I am not sure why. It is telling me that this line: if(temp > data[[k]][[k2]]) { is of argument length 0. Here is the block which is not that big:
for(k in 1:length(data)) {
temp <- 0
for(k2 in 3:length(data[[k]])) {
print(data[[k]][[k2]])
if(temp > data[[k]][[k2]]) {
temp <- data[[k]][[k2]]
}
fMax[k] <- temp
k2 <- k2 + 1
}
k <- k + 1
}
example of what is in data[[k]][[k2]]:
[1] "3050"
[1] "3051"
[1] "3054"
[1] "3054"
[1] "3052"
[1] "3053"
[1] "3059"
[1] "3059"
[1] "3057"
[1] "3060"
[1] "3063"
[1] "3060"
[1] "3068"
[1] "3067"
[1] "3079"
[1] "3085"
[1] "3094"
[1] "3107"
[1] "3121"
[1] "3135"
[1] "3147"
[1] "3161"
[1] "3200"
[1] "3237"
[1] "3264"
[1] "3274"
[1] "3284"
[1] "3289"
[1] "3292"
[1] "3300"
[1] "3301"
[1] "3303"
[1] "3306"
[1] "3310"
[1] "3312"
[1] "3313"
[1] "3319"
[1] "3314"
[1] "3318"
[1] "3318"
[1] "3320"
[1] "3322"
[1] "3322"
[1] "3322"
[1] "3328"
[1] "3332"
[1] "3338"
[1] "3350"
[1] "3358"
[1] "3378"
[1] "3395"
[1] "3402"
[1] "3875"
[1] "3950"
[1] "3988"
[1] "4018"
[1] "4039"
[1] "4048"
[1] "4057"
[1] "4062"
[1] "4067"
[1] "4076"
[1] "4082"
[1] "4085"
[1] "4092"
[1] "4098"
[1] "4099"
[1] "4101"
[1] "4107"
[1] "4119"
[1] "4139"
[1] "4164"
[1] "4231"
[1] "4347"
[1] "4559"
"argument is of length zero" is a very specific problem that comes from one of my least-liked elements of R. Let me demonstrate the problem:
> FALSE == "turnip"
[1] FALSE
> TRUE == "turnip"
[1] FALSE
> NA == "turnip"
[1] NA
> NULL == "turnip"
logical(0)
As you can see, comparisons to a NULL not only don't produce a boolean value, they don't produce a value at all - and control flows tend to expect that a check will produce some kind of output. When they produce a zero-length output... "argument is of length zero".
(I have a very long rant about why this infuriates me so much. It can wait.)
So, my question; what's the output of sum(is.null(data[[k]]))? If it's not 0, you have NULL values embedded in your dataset and will need to either remove the relevant rows, or change the check to
if(!is.null(data[[k]][[k2]]) & temp > data[[k]][[k2]]){
#do stuff
}
Hopefully that helps; it's hard to tell without the entire dataset. If it doesn't help, and the problem is not a NULL value getting in somewhere, I'm afraid I have no idea.
The same error message results not only for null but also for e.g. factor(0). In this case, the query must be if(length(element) > 0 & otherCondition) or better check both cases with if(!is.null(element) & length(element) > 0 & otherCondition).
You can use isTRUE for such cases. isTRUE is the same as { is.logical(x) && length(x) == 1 && !is.na(x) && x }
If you use shiny there you could use isTruthy which covers the following cases:
FALSE
NULL
""
An empty atomic vector
An atomic vector that contains only missing values
A logical vector that contains all FALSE or missing values
An object of class "try-error"
A value that represents an unclicked actionButton()
I spent an entire day bashing my head against this, the solution turned out to be simple..
R isn't zero-index.
Every programming language that I've used before has it's data start at 0, R starts at 1.
The result is an off-by-one error but in the opposite direction of the usual.
going out of bounds on a data structure returns null and comparing null in an if statement gives the argument is of length zero error. The confusion started because the dataset doesn't contain any null, and starting at position [0] like any other pgramming language turned out to be out of bounds.
Perhaps starting at 1 makes more sense to people with no programming experience (the target market for R?) but for a programmer is a real head scratcher if you're unaware of this.
The argument is of length zero takes places when you get an output as an integer of length 0 and not a NULL output.i.e.,
integer(0).
You can further verify my point by finding the class of your output-
>class(output)
"integer"
The simplest solution to the problem is to change your for loop statement :
Instead of using
for (i in **0**:n))
Use
for (i in **1**:n))
In my case, I just wanted to see the first position of the character as follows
htagPos <- which(strsplit(val, "")[[1]] == "#")
if(htagPos == 1){
next
}# this did now work:(
So I had to check the length of the result first before checking the value
htagPos <- which(strsplit(val, "")[[1]] == "#")
if(length(htagPos) >= 1 && htagPos == 1){
next
}
I see why most people prefer python...
So the other possibility for this error can be when the condition in IF is a return value from other function.
For example,
check <- function (value) {
if (value == 0) {
return TRUE
}
Now,
If this function is called like this:
if(check(value)) {
do something
}
So here, let's assume the value is not 0, there is no return statement for that case. In this case too, you'll get "argument is of length zero" error.
Hope this is helpful!
String data structures have the last data addressed nulled so use max(data) instead of data[last].
https://www.geeksforgeeks.org/string-data-structure/
For example,a string with 4 elements will have a number element in it's 5th element.

Resources