47

I want put stop condition inside a function. The condition is that if first and second elements should match perfectly in order and length.

A <- c("A", "B", "C", "D")
B <- A
C <- c("A", "C", "C", "E")

> A == B
[1] TRUE TRUE TRUE TRUE

This is good situation to go forward

> A == C

[1]  TRUE  FALSE TRUE FALSE

Since there is one false this condition to stop and output that the condition doesnot hold at 2 and 4 th column.

if (A != B) {
           stop("error the A and B does not match at column 2 and 4"} else {
            cat ("I am fine") 
                }
Warning message:
In if (A != B) (stop("error 1")) :
  the condition has length > 1 and only the first element will be used

Am I missing something obvious ? Also I can output where error positions are ?

Paul Hiemstra
  • 59,984
  • 12
  • 142
  • 149
jon
  • 11,186
  • 19
  • 80
  • 132

3 Answers3

72

all is one option:

> A <- c("A", "B", "C", "D")
> B <- A
> C <- c("A", "C", "C", "E")

> all(A==B)
[1] TRUE
> all(A==C)
[1] FALSE

But you may have to watch out for recycling:

> D <- c("A","B","A","B")
> E <- c("A","B")
> all(D==E)
[1] TRUE
> all(length(D)==length(E)) && all(D==E)
[1] FALSE

The documentation for length says it currently only outputs an integer of length 1, but that it may change in the future, so that's why I wrapped the length test in all.

Aaron left Stack Overflow
  • 36,704
  • 7
  • 77
  • 142
  • 8
    Your caution about recycling is why you should use `isTRUE(all.equal(D,E))`. – Joshua Ulrich Apr 29 '12 at 20:58
  • 1
    Looking at the code for `all.equal.character` was enlightening to me. Because of the "near-equality" aspect of it for floats I'd assumed it did something funny for other things too. I'm not sure what, in retrospect. But the only perhaps unwanted thing it does is to check for equality of all the attributes, including names. It also takes more care with `NA`s than my simple code above does. – Aaron left Stack Overflow Apr 30 '12 at 01:33
35

Are they identical?

> identical(A,C)
[1] FALSE

Which elements disagree:

> which(A != C)
[1] 2 4
Matthew Lundberg
  • 42,009
  • 6
  • 90
  • 112
7

I'd probably use all.equal and which to get the information you want. It's not recommended to use all.equal in an if...else block for some reason, so we wrap it in isTRUE(). See ?all.equal for more:

foo <- function(A,B){
  if (!isTRUE(all.equal(A,B))){
    mismatches <- paste(which(A != B), collapse = ",")
    stop("error the A and B does not match at the following columns: ", mismatches )
  } else {
    message("Yahtzee!")
  }
}

And in use:

> foo(A,A)
Yahtzee!
> foo(A,B)
Yahtzee!
> foo(A,C)
Error in foo(A, C) : 
  error the A and B does not match at the following columns: 2,4
Chase
  • 67,710
  • 18
  • 144
  • 161