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.
Related
rquote <- "r's internals are irrefutably intriguing"
chars <- strsplit(rquote, split = "")[[1]]
This question has been asked before on this forum and has one answer on it but I couldn't understand anything from that answer, so here I am asking this question again.
In the above code what is the meaning of [[1]] ?
The program that I'm trying to run:
rquote <- "r's internals are irrefutably intriguing"
chars <- strsplit(rquote, split = "")[[1]]
rcount <- 0
for (char in chars) {
if (char == "r") {
rcount <- rcount + 1
}
if (char == "u") {
break
}
}
print(rcount)
When I don't use [[1]] I get the following warning message in for loop and I get a wrong output of 1 for rcount instead of 5:
Warning message: the condition has length > 1 and only the first element will be used
strsplit is vectorized. That means it splits each element of a vector into a vectors. To handle this vector of vectors it returns a list in which a slot (indexed by [[) corresponds to a element of the input vector.
If you use the function on a one element vector (single string as you do), you get a one-slot list. Using [[1]] right after strsplit() selects the first slot of the list - the anticipated vector.
Unfortunately, your list chars works in a for loop - you have one iteration with the one slot. In if you compare the vector of letters against "r" which throws the warning. Since the first element of the comparison is TRUE, the condition holds and rcount is rised by 1 = your result. Since you are not indexing the letters but the one phrase, the cycle stops there.
Maybe if you run something like strsplit(c("one", "two"), split="") , the outcome will be more straightforward.
> strsplit(c("one", "two"), split="")
[[1]]
[1] "o" "n" "e"
[[2]]
[1] "t" "w" "o"
> strsplit(c("one", "two"), split="")[[1]]
[1] "o" "n" "e"
> strsplit(c("one"), split="")[[1]][2]
[1] "n"
We'll start with the below as data, without [[1]]:
rquote <- "r's internals are irrefutably intriguing"
chars2 <- strsplit(rquote, split = "")
class(chars2)
[1] "list"
It is always good to have an estimate of your return value, your above '5'. We have both length and lengths.
length(chars2)
[1] 1 # our list
lengths(chars2)
[1] 40 # elements within our list
We'll use lengths in our for loop for counter, and, as you did, establish a receiver vector outside the loop,
rcount2 <- 0
for (i in 1:lengths(chars2)) {
if (chars2[[1]][i] == 'r') {
rcount2 <- rcount2 +1
}
if (chars2[[1]][i] == 'u') {
break
}
}
print(rcount2)
[1] 6
length(which(chars2[[1]] == 'r')) # as a check, and another way to estimate
[1] 6
Now supposing, rather than list, we have a character vector:
chars1 <- strsplit(rquote, split = '')[[1]]
length(chars1)
[1] 40
rcount1 <- 0
for(i in 1:length(chars1)) {
if(chars1[i] == 'r') {
rcount1 <- rcount1 +1
}
if (chars1[i] == 'u') {
break
}
}
print(rcount1)
[1] 5
length(which(chars1 == 'r'))
[1] 6
Hey, there's your '5'. What's going on here? Head scratch...
all.equal(chars1, unlist(chars2))
[1] TRUE
That break should just give us 5 'r' before a 'u' is encountered. What's happening when it's a list (or does that matter...?), how does the final r make it into rcount2?
And this is where the fun begins. Jeez. break for coffee and thinking. Runs okay. Usual morning hallucination. They come and go. But, as a final note, when you really want to torture yourself, put browser() inside your for loop and step thru.
Browse[1]> i
[1] 24
Browse[1]> n
debug at #7: break
Browse[1]> chars2[[1]][i] == 'u'
[1] TRUE
Browse[1]> n
> rcount2
[1] 5
How is this possible?
> a=TC_df$temp[561]
> a
[1] 15.6
> a==15.6
[1] FALSE
> a=="15.6"
[1] TRUE
> class(a)
[1] "numeric"
You compare a number with string with == operator. Use identical instead.
Start with:
> a=15.60000000000001
> a
[1] 15.6
> a=="15.6"
[1] TRUE
> a==15.6
[1] FALSE
A kind of such a number is in your case stored in the variable a.
The options(digits...) controls the number of digits to print when printing numeric values. Now set the number of digits to print to 16:
> options(digits=16)
> a
[1] 15.60000000000001
> toString(a)
[1] "15.6"
Do you see what happened? The identical does not suffer from this problem.
I am looking for a method in R to run the block inside the if statement only the first time the if statement is evaluated as TRUE, but the block would not be run again even if the if condition is TRUE again. Specifically, the method would be useful in a loop.
This would be the "once" statement (it is called so in some exotic languages).
Example:
for (id in id_list){ # runs over a list of several id's which are random
if (id == "snake"){ # I want to run this block only the first time and NOT each time id == "snake"
# now, do some calculations
# ...
}
# do some other calculations by default for all other runs inside the loop
# ...
}
I would be also curious to know how would this work in Python.
1) duplicated Using the test input shown in the first line iterate over an index and add a condition using duplicated. This avoids using a flag making it less error prone.
id_list <- c("a", "snake", "b", "snake") # test input
dup <- duplicated(id_list)
for(i in seq_along(id_list)) {
if (id_list[i] == "snake" && (!dup)[i]) print("snake")
print(i)
}
giving:
[1] 1
[1] "snake"
[1] 2
[1] 3
[1] 4
2) match Another approach to determine which iteration represents the first instance of snake and using that in the condition.
ix <- match("snake", id_list, nomatch = 0)
for(i in seq_along(id_list)) {
if (i == ix) print("snake")
print(i)
}
giving:
[1] 1
[1] "snake"
[1] 2
[1] 3
[1] 4
3) once
Another approach is to create a once function which returns TRUE the first time it is run and FALSE otherwise. This does use a mutable variable, x, (similar to a flag) but at least it is encapsulated. The genOnce function outputs a fresh once function.
It is important to use && in the condition to ensure that the right hand side of && is only run if the left hand side is TRUE. & does not have that short circuiting property.
genOnce <- function(x = 0) function() (x <<- x + 1) == 1
once <- genOnce()
for(id in id_list) {
if (id == "snake" && once()) print("***")
print(id)
}
giving:
[1] "a"
[1] "***"
[1] "snake"
[1] "b"
[1] "snake"
Suggested solution using a 'global' variable (i.e. 'flag') to denote first pass into if clause:
first <- TRUE
for (i in 1:5) {
if (first & i > 0) {
print("run this block only the first time")
first <- FALSE
}
print("do some other calculations")
}
Output:
[1] "run this block only the first time"
[1] "do some other calculations"
[1] "do some other calculations"
[1] "do some other calculations"
[1] "do some other calculations"
[1] "do some other calculations"
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
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.