Janet
Janet

Reputation: 225

R argument is of length zero when using names(vector) in IF statement

I have a dataframe and a vector like this:

# sample data
IDd= c(seq(1,8))
BTD= c("A","B","AB","O","AB","AB","O","O")
fg= c(rep(0.0025, each=2),rep(0.00125, each=2),rep(0.0011, each=2),rep(0.0015, each=2))
data_D=data.frame(IDd,BTD,A=c(rep(0,5),1,1,1),B=c(rep(0,6),1,1),C=c(rep(1,7),0),D=rep(1,8),E=c(rep(0,5),rep(1,2),0),fg,stringsAsFactors=FALSE)

data_D
  IDd BTD A B C D E      fg
2   2   A 0 0 1 1 0 0.00250
4   4  AB 0 0 1 1 0 0.00125
5   5   B 0 0 1 1 0 0.00110
6   6   O 0 0 1 1 0 0.00110
7   7  AB 0 0 1 1 0 0.00150
8   8  AB 1 0 1 1 1 0.00150
1   1   O 1 1 0 1 0 0.00250
3   3   O 1 1 1 1 1 0.00125

# character vector 
Rvec=c(1,"A",0,0,0,0,1,0.0031)
names(Rvec)=c("Idr","BTR","A","B","C","D","E","fg")
Rvec
     Idr      BTR        A        B        C        D        E       fg 
     "1"      "A"      "0"      "0"      "0"      "0"      "1" "0.0031" 

Everytime i want to check names of my vector or dataframe i got an error. Here is the code

check.names=function(Rvec,Data){ 
  Rvec=as.vector(Rvec)
  Data=as.data.frame(Data)
if(names(Data)[3:ncol(Data)] != names(Rvec)[3:length(Rvec)]) stop("Error")
if(names(Rvec)[2] != "BTR") {
  names(Rvec)[2] = "BTR" 
 }
}

check.names(Rvec= Rvec, Data=data_D)
# Error in if (names(Data)[3:ncol(Data)] != names(Rvec)[3:length(Rvec)])
 # stop("Error") : 
 # argument is of length zero

I keep getting this error whenever i used names in both if statement. Do you know what cause this problem? I also took a look at "argument is of length zero" in if statement, r if statement meet error: argument is of length zero, but still can not resolve this issue. The weird thing is when i run the if statement separately i do not get any errors but once within the function i get the error message. Thank you for your help .

@DanY, i just modified the line all.equal in your answer and it is working now

# first modified vector
 names(Rvec)[2]="btr"
 names(Rvec)[3]="k"
 Rvec
     Idr      btr        k        B        C        D        E       fg 
     "1"      "A"      "0"      "0"      "0"      "0"      "1" "0.0031" 

# second modified vector 
Rvec1
     Idr      btr        A        B        C        D        E       fg 
     "1"      "A"      "0"      "0"      "0"      "0"      "1" "0.0031" 
# modified function

check.names=function(Rvec,Data){
  if(!is.vector(Rvec)) stop("Rvec must be a vector")
  if(!is.data.frame(Data)) stop("Data must be a data.frame")
  dnames <- names(Data)[3:ncol(Data)]
  rnames <- names(Rvec)[3:length(Rvec)]
  if(!isTRUE(all.equal(dnames, rnames))) stop("Names don't match")
  if(names(Rvec)[2] != "BTR") {
    names(Rvec)[2] = "BTR" 
  }  
  
}

# test for first modified vector Rvec
check.names(Rvec= Rvec, Data=data_D)
# Error in check.names(Rvec = Rvec, Data = data_D) : Names don't match

# test for second modified vector Rvec1
a=check.names(Rvec= Rvec1, Data=data_D)
a
[1] "BTR"

Upvotes: 0

Views: 284

Answers (1)

DanY
DanY

Reputation: 6073

Your function uses the line

Rvec = as.vector(Rvec)

The help documentation for as.vector() states that "if the result is atomic, all attributes are removed." This means that element names are dropped when you run as.vector().

One solution is not to coerce Rvec to be a vector, but rather to check that it is a vector. You'll also need to change the if() statement in your third line to either an ifelse() or an all.equal(). Here's one solution with those 2 fixes (replace the ... with the rest of your code):

check.names <- function(Rvec,Data){ 
    if(!is.vector(Rvec)) stop("Rvec must be a vector")
    if(!is.data.frame(Data)) stop("Data must be a data.frame")
    
    dnames <- names(Data)[3:ncol(Data)]
    rnames <- names(Rvec)[3:length(Rvec)]
    
    if(!all.equal(dnames, rnames)) stop("Names don't match")
    ...
}

Upvotes: 2

Related Questions