2

I want to compute my data according to rule that number+W is number*2.

dat="1W   16   2W   16
      1   16   2W    0
     1W   16   16    0
      4   64   64    0"     
data=read.table(text=dat,header=F)
apply(data,c(1,2),function(y){
     if(grep(pattern="W",y) ==1 )
     {  gsub("W",paste("*",2,sep=""),y)->s;
         eval(parse(text=s));
      } else 
        {y <- y }
      })

But I get the output:

Error in if (grep(pattern = "W", y) == 1) { : argument is of length zero

Why? If y matches "W" then the value is 1, what is wrong with my code?

joran
  • 169,992
  • 32
  • 429
  • 468
showkey
  • 482
  • 42
  • 140
  • 295
  • 1
    As SimonO101 noted, you're working far too hard. First of all, `y<-y` is a waste of time, so just `else y` suffices. Next, it's not clear why you want to start with character strings. I strongly recommend going back and fixing whatever code creates that mix of numbers and "numberW" . Heck, you might as well use `sfsmisc:AsciiToInt()` , replace instances of `87` with `50`, and convert back :-) – Carl Witthoft Jan 02 '14 at 13:33

3 Answers3

8

Your query can be illustrated with the following example:

grep(pattern="W","huh")
# integer(0)

No match results in a vector of length 0, hence the error. Instead use grepl, i.e. if( grepl( "W" , y ) ).

grepl has the return value TRUE or FALSE.

As a side note, eval( parse( "sometext" ) ) is variously thought of as not a good idea. You could try using the following untidy lapply statement instead (which will be better than apply because you don't have to convert to a matrix first):

data.frame( lapply( data , function(x) 
                                ifelse( grepl("W",x) , 
                                        as.integer( gsub("W","",x) ) * 2L , 
                                        x ) ) )
#  V1 V2 V3 V4
#1  2 16  4 16
#2  1 16  4  0
#3  2 16  1  0
#4  3 64  3  0
Richie Cotton
  • 118,240
  • 47
  • 247
  • 360
Simon O'Hanlon
  • 58,647
  • 14
  • 142
  • 184
  • what is the meaning of integer(0) and logical(0) ? – showkey Jan 02 '14 at 13:27
  • 1
    Try `logical(1)` and then `logical(3)` and see what happens. They are logical vectors (filled with the default value of `FALSE`) of length 1 and 3 respectively. `logical(0)` means a vector of type `logical` but with no values in it. `integer(0)` is the same thing but for integers. – Simon O'Hanlon Jan 02 '14 at 13:30
0

Here's a rather bizarre approach, which does work just fine:

library(sfsmisc)

foo<- c('2','23', 'W4','W53','17')
bar<-sapply(foo, function(x)AsciiToInt(x))
barw<-sapply(bar,function(x)x[x!=87])
bard<-logical(length(foo))
for (i in 1:length(foo) ) bard[i]<-length(barw[[i]])== length(bar[[i]])

foow<-vector()
for(i in 1:length(foo)) foow[i]<-as.numeric(paste0(chars8bit(barw[[i]]),collapse='') ) *(1+!bard[i])
Carl Witthoft
  • 20,573
  • 9
  • 43
  • 73
0

R 3.4.1 Error: "argument is of length zero" in if statement

If you pass an empty vector into an if statement such as:

myvariable = c()
if (myvariable){ 
    print("hello") 
} 

You will get an error:

Error in if (myvariable) { : argument is of length zero

Empty R vectors can bubble up data-type errors through functions like grep, for example:

if (grepl("foo", c(), fixed = TRUE)){ 
    print("yes") 
} 

Which fails:

Error in if (grepl("foo", c(), fixed = TRUE)) { : 
  argument is of length zero

So the remedy is to do more type checking of your variables before feeding them as arguments to either if statements, or functions like grep.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335