[R] removing values from a vector, where both the value and its name are the same?

Marc Schwartz marc_schwartz at comcast.net
Fri Jun 15 20:49:45 CEST 2007


On Fri, 2007-06-15 at 11:19 -0700, new ruser wrote:
> I have an array such as:
> 
> x=c(sum=77, min=4,max=9, count=5, min=4,max=9, count=8 ,  test=77)
> 
> I wish to remove values where both the name and the value are identical.
> 
> eg. i wish to end up with:
> x2=c(sum=77, min=4,max=9, count=5, count=8, test=77)
>  
> What is the "best" way to do this?

Not sure if this is the best way, but since you need to compare both the
values and their name attributes for 'uniqueness':

> x[!(duplicated(x) & duplicated(names(x)))]
  sum   min   max count count  test 
   77     4     9     5     8    77 


What is being done is to first compare the values for duplicates. Note
that the second value is identified as the duplicate, not the first:

> duplicated(x)
[1] FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE  TRUE

and then compare the names for duplicates:

> duplicated(names(x))
[1] FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE


Then compare the two logical vectors and get the indices where BOTH are
TRUE:

> (duplicated(x) & duplicated(names(x)))
[1] FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE


Now, negate the relation:

> !(duplicated(x) & duplicated(names(x)))
[1]  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE


and return the values in 'x' that satisfy the logical indices:

> x[!(duplicated(x) & duplicated(names(x)))]
  sum   min   max count count  test 
   77     4     9     5     8    77 



See ?duplicated.  You might also want to look
at ?unique, ?identical, ?all.equal and ?isTRUE.

Note that the above example will likely fail if any of the values are
floats:

> duplicated(c(0.5 - 0.4, 0.1))
[1] FALSE FALSE

in which case, you would need to use a looping structure where the value
comparisons use isTrue(all.equal(...)) instead.


HTH,

Marc Schwartz



More information about the R-help mailing list