0

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"
Janet
  • 225
  • 1
  • 6

1 Answers1

2

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")
    ...
}
DanY
  • 5,920
  • 1
  • 13
  • 33
  • Now @DanY i get the message: `the condition has length > 1 and only the first element will be used` (when i removed the first 2 lines in the function and replace it with your `if` cheks) ?? – Janet Nov 12 '20 at 21:45
  • OMG @DanY now i get a different error message `Error in all.equal.default(dnames == rnames) : argument "current" is missing, with no default ` when add `if(!all.equal(dnames==rnames)) stop("Names don't match")`. I dont understand i dont have any argument called `current`? – Janet Nov 12 '20 at 22:02
  • Sure thing i learned a lot from you! i thank you very much for your patience @DanY! It seems to work, i will test it with different vector right now! – Janet Nov 12 '20 at 22:07
  • When i try a different vector with different names i dont get `stop()` message, instead i get this error message `Error in !all.equal(dnames, rnames) : invalid argument type`. – Janet Nov 12 '20 at 22:14
  • 1
    it is working now @DanY, i just changed `!all.equal(dnames, rnames)` to `isTrue(all.equal(dnames, rnames))` – Janet Nov 12 '20 at 22:25
  • 1
    Thank you @DanY for your help, really appreciate it! – Janet Nov 12 '20 at 22:38