trastorno tipos tiene problemas primaria padres niños mala los influyen infantil inadecuadas hijos hijo escuela detectar conductas conducta comportamiento como años r

tipos - ¿Cómo extender el comportamiento `==` a los vectores que incluyen NA?



tipos de comportamiento en los niños (4)

¿Qué hay de usar identical() envuelto en mapply()

a <- c( 1 , 2 , 3 ) b <- c( 1 , 2 , 4 ) mapply(identical,a,b) #[1] TRUE TRUE FALSE a <- c( 1 , NA , 3 ) b <- c( 1 , NA , 4 ) mapply(identical,a,b) #[1] TRUE TRUE FALSE a <- c( 1 , NA , 3 ) b <- c( 1 , 2 , 4 ) mapply(identical,a,b) #[1] TRUE FALSE FALSE

Además, si necesita comparar los resultados de los cálculos, podría deshacerse de identical() e ir con isTRUE(all.equal()) como tal

mapply(FUN=function(x,y){isTRUE(all.equal(x,y))}, a, b)

lo que da los mismos resultados, pero puede tratar mejor los problemas de redondeo. Como

a<-.3/3 b<-.1 mapply(FUN=function(x,y){isTRUE(all.equal(x,y))}, a, b) #[1] TRUE mapply(identical,a,b) #[1] FALSE

Creo que este último ejemplo all.equal muchas de las soluciones propuestas, pero cambiar a all.equal lugar de == probablemente funcionaría para todas ellas.

He fallado completamente en la búsqueda de otra discusión r-help o Stack Overflow sobre este problema específico. Lo siento si está en algún lugar obvio. Creo que estoy buscando la forma más fácil de obtener el signo == de R para no devolver nunca NA.

# Example # # Say I have two vectors a <- c( 1 , 2 , 3 ) b <- c( 1 , 2 , 4 ) # And want to test if each element in the first # is identical to each element in the second: a == b # It does what I want perfectly: # TRUE TRUE FALSE # But if either vector contains a missing, # the `==` operator returns an incorrect result: a <- c( 1 , NA , 3 ) b <- c( 1 , NA , 4 ) # Here I''d want TRUE TRUE FALSE a == b # But I get TRUE NA FALSE a <- c( 1 , NA , 3 ) b <- c( 1 , 2 , 4 ) # Here I''d want TRUE FALSE FALSE a == b # But I get TRUE NA FALSE again.

Obtengo el resultado que quiero con:

mapply( `%in%` , a , b )

Pero mapply parece pesado.

¿Hay una solución más intuitiva para esto?


Otra opción, pero ¿es mejor que mapply(''%in%'', a , b) ?

(!is.na(a) & !is.na(b) & a==b) | (is.na(a) & is.na(b))

Siguiendo la sugerencia de @AnthonyDamico, creación del operador "mutt":

"%==%" <- function(a, b) (!is.na(a) & !is.na(b) & a==b) | (is.na(a) & is.na(b))

Edición: o, versión ligeramente diferente y más corta de @Frank (que también es más eficiente)

"%==%" <- function(a, b) (is.na(a) & is.na(b)) | (!is.na(eq <- a==b) & eq)

Con los diferentes ejemplos:

a <- c( 1 , 2 , 3 ) b <- c( 1 , 2 , 4 ) a %==% b # [1] TRUE TRUE FALSE a <- c( 1 , NA , 3 ) b <- c( 1 , NA , 4 ) a %==% b # [1] TRUE TRUE FALSE a <- c( 1 , NA , 3 ) b <- c( 1 , 2 , 4 ) a %==% b #[1] TRUE FALSE FALSE a <- c( 1 , NA , 3 ) b <- c( 3 , NA , 1 ) a %==% b #[1] FALSE TRUE FALSE


Suponiendo que no tenemos un número relativo grande de NA , la solución vectorizada propuesta desperdicia algunos recursos comparando valores que ya han sido resueltos por a==b .

Por lo general, podemos asumir que las NAs son pocas, por lo que vale la pena calcular a==b primero y luego tratar las NAs separado, a pesar de los pasos adicionales y las variables temporales:

`%==%` <- function(a,b){ x <- a==b na_x <- which(is.na(x)) x[na_x] <- is.na(a[na_x]) & is.na(b[na_x]) x }

Comprobar salida

a <- c( 1 , 2 , 3 ) b <- c( 1 , 2 , 4 ) a %==% b # [1] TRUE TRUE FALSE a <- c( 1 , NA , 3 ) b <- c( 1 , NA , 4 ) a %==% b # [1] TRUE TRUE FALSE a <- c( 1 , NA , 3 ) b <- c( 1 , 2 , 4 ) a %==% b # [1] TRUE FALSE FALSE

Puntos de referencia

Estoy reproduciendo a continuación el punto de referencia de @ akrun con las soluciones más rápidas y n = 100.

set.seed(24) a <- sample(c(1:10, NA), 1e6, replace=TRUE) b <- sample(c(1:20, NA), 1e6, replace=TRUE) mm <- function(){ x <- a==b na_x <- which(is.na(x)) x[na_x] <- is.na(a[na_x]) & is.na(b[na_x]) x } akrun1 <- function() {replace(a, is.na(a), Inf)==replace(b, is.na(b), Inf)} cathG <- function() {(!is.na(a) & !is.na(b) & a==b) | (is.na(a) & is.na(b))} docend <- function() {replace(a, which(is.na(a)), Inf)==replace(b, which(is.na(b)), Inf)} library(microbenchmark) microbenchmark(mm(),akrun1(),cathG(),docend(), unit=''relative'', times=100L) # Unit: relative # expr min lq mean median uq max neval # mm() 1.000000 1.000000 1.000000 1.000000 1.000000 1.0000000 100 # akrun1() 1.667242 1.884185 1.815392 1.642581 1.765238 0.9973017 100 # cathG() 2.447168 2.449597 2.118306 2.201346 2.358105 1.1421577 100 # docend() 1.683817 1.950970 1.756481 1.745400 2.007889 1.2264461 100

Extendiendo ==

Como la pregunta original es realmente encontrar:

la forma más fácil de obtener el signo == R para no devolver nunca NAs

Aquí hay una manera, donde definimos una nueva clase na_comparable . Solo uno de los vectores debe ser de esta clase ya que el otro será obligado a ello.

na_comparable <- setClass("na_comparable", contains = "numeric") `==.na_comparable` <- function(a,b){ x <- unclass(a) == unclass(b) # inefficient but I don''t know how to force the default `==` na_x <- which(is.na(x)) x[na_x] <- is.na(a[na_x]) & is.na(b[na_x]) x } `!=.na_comparable` <- Negate(`==.na_comparable`) a <- na_comparable(a) a == b # [1] TRUE TRUE FALSE b == a # [1] TRUE TRUE FALSE a != b # [1] FALSE FALSE TRUE b != a # [1] FALSE FALSE TRUE

En una cadena dplyr se podría usar convenientemente de esta manera:

data.frame(a=c(1,NA,3),b=c(1,NA,4)) %>% mutate(a = na_comparable(a), c = a==b, d= a!=b) # a b c d # 1 1 1 TRUE FALSE # 2 NA NA TRUE FALSE # 3 3 4 FALSE TRUE

Con este enfoque, en caso de que necesite actualizar el código para tener en cuenta las NAs que estuvieron ausentes antes, puede configurarlo con una sola llamada na_comparable lugar de transformar sus datos iniciales o reemplazar todos sus == con %==% en la línea.


Tu podrías intentar

replace(a, is.na(a), Inf)==replace(b, is.na(b), Inf)

O una variación más rápida sugerida por @docendo discimus

replace(a, which(is.na(a)), Inf)==replace(b, which(is.na(b)), Inf)

Basado en los diferentes escenarios.

1.

a <- c( 1 , 2 , 3 ) b <- c( 1 , 2 , 4 ) akrun1() #[1] TRUE TRUE FALSE

2.

a <- c( 1 , NA , 3 ) b <- c( 1 , NA , 4 ) akrun1() #[1] TRUE TRUE FALSE

3.

a <- c( 1 , NA , 3 ) b <- c( 1 , 2 , 4 ) akrun1() #[1] TRUE FALSE FALSE

Puntos de referencia

set.seed(24) a <- sample(c(1:10, NA), 1e6, replace=TRUE) b <- sample(c(1:20, NA), 1e6, replace=TRUE) akrun1 <- function() {replace(a, is.na(a), Inf)==replace(b, is.na(b), Inf)} cathG <- function() {(!is.na(a) & !is.na(b) & a==b) | (is.na(a) & is.na(b))} anthony <- function() {mapply(`%in%`, a, b)} webb <- function() {ifelse(is.na(a),is.na(b),a==b)} docend <- function() {replace(a, which(is.na(a)), Inf)==replace(b, which(is.na(b)), Inf)} library(microbenchmark) microbenchmark(akrun1(), cathG(), anthony(), webb(),docend(), unit=''relative'', times=20L) #Unit: relative # expr min lq mean median uq max # akrun1() 3.050200 3.035625 3.007196 2.963916 2.977490 3.083658 # cathG() 4.829972 4.893266 4.843585 4.790466 4.816472 4.939316 # anthony() 190.499027 224.389971 215.792965 217.647702 215.503308 212.356051 # webb() 14.000363 14.366572 15.412527 14.095947 14.671741 19.735746 # docend() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 # neval cld # 20 a # 20 a # 20 c # 20 b # 20 a