Justin Kong
Justin Kong

Reputation: 37

About missing value where TRUE/FALSE needed in R

I want to return the number of times in string vector v that the element at the next successive index has more characters than the current index. Here's my code

BiggerPairs <- function (v) {
numberOfTimes <- 0
for (i in 1:length(v)) {
if((nchar(v[i+1])) > (nchar(v[i]))) {
numberOfTimes <- numberOfTimes + 1
}
}
return(numberOfTimes)
}
}

Error message:

missing value where TRUE/FALSE needed.

I do not know why this happens.

Upvotes: 1

Views: 36664

Answers (2)

Brandon
Brandon

Reputation: 1904

The error you are getting is saying that your code is trying to evaluate a missing value (NA) where it expects a number. There are likely one of two reasons for this.

  1. You have NA's in your vector v (I suspect this is not the actual issue)
  2. The loop you wrote is from 1:length(v), however, on the last iteration, this will try the loop to try to compare v[n+1] > v[n]. There is no v[n+1], thus this is a missing value and you get an error.

To remove NAs, try the following code:

v <- na.omit(v)

To improve your loop, try the following code:

for(i in 1:(length(v) -1)) {
    if(nchar(v[i + 1]) > nchar(v[i])) {
        numberOfTimes <- numberOfTimes + 1
    }
}

Here is some example dummy code.

# create random 15 numbers
set.seed(1)
v <- rnorm(15)

# accessing the 16th element produces an NA
v[16]
#[1] NA

# if we add an NA and try to do a comparison, we get an error
v[10] <- NA
v[10] > v[9]
#[1] NA

# if we remove NAs and limit our loop to N-1, we should get a fair comparison
v <- na.omit(v)
numberOfTimes <- 0

for(i in 1:(length(v) -1)) {
    if(nchar(v[i + 1]) > nchar(v[i])) {
        numberOfTimes <- numberOfTimes + 1
    }
}

numberOfTimes
#[1] 5

Upvotes: 7

Maurits Evers
Maurits Evers

Reputation: 50678

Is this what you're after? I don't think there is any need for a for loop.

I'm generating some sample data, since you don't provide any.

# Generate some sample data
set.seed(2017);
v <- sapply(sample(30, 10), function(x)
    paste(sample(letters, x, replace = T), collapse = ""))
v;
#[1] "raalmkksyvqjytfxqibgwaifxqdc" "enopfcznbrutnwjq"
#[3] "thfzoxgjptsmec"               "qrzrdwzj"
#[5] "knkydwnxgfdejcwqnovdv"        "fxexzbfpampbadbyeypk"
#[7] "c"                            "jiukokceniv"
#[9] "qpfifsftlflxwgfhfbzzszl"      "foltth"

The following vector marks the positions with 1 in v where entries have more characters than the previous entry.

# The following vector has the same length as v and
# returns 1 at the index position i where 
# nchar(v[i]) > nchar(v[i-1])
idx <- c(0, diff(nchar(v)) > 0);
idx;
# [1] 0 0 0 0 1 0 0 1 1 0

If you're just interested in whether there is any entry with more characters than the previous entry, you can do this:

# If you just want to test if there is any position where
# nchar(v[i+1]) > nchar(v[i]) you can do
any(idx == 1);
#[1] TRUE

Or count the number of occurrences:

sum(idx);
#[1] 3

Upvotes: 2

Related Questions