Saltar al contenido

Reemplazar valores negativos por cero

Ya no tienes que investigar más en otras páginas porque has llegado al sitio adecuado, tenemos la solución que buscas sin problema.

Solución:

Gracias por el ejemplo reproducible. Esto es algo de R bastante básico. Puede asignar a los elementos seleccionados de un vector (observe un array tiene dimensiones, y lo que has dado es un vector, no un array):

> pred_precipitation[pred_precipitation<0] <- 0
> pred_precipitation
 [1] 1.2091281 0.0000000 7.7665555 0.0000000 0.0000000 0.0000000 0.5151504 0.0000000 1.8281251
[10] 0.5098688 2.8370263 0.4895606 1.5152191 4.1740177 7.1527742 2.8992215 4.5322934 6.7180530
[19] 0.0000000 1.1914052 3.6152333 0.0000000 0.3778717 0.0000000 1.4940469

¡Guerras de puntos de referencia!

@James encontró un método aún más rápido y lo dejó en un comentario. Lo voté a favor, aunque solo sea porque sé que su victoria será de corta duración.

Primero, intento compilar, pero eso no parece ayudar a nadie:

p <- rnorm(10000)
gsk3 <- function(x)  x[x<0] <- 0; x 
jmsigner <- function(x) ifelse(x<0, 0, x)
joshua <- function(x) pmin(x,0)
james <- function(x) (abs(x)+x)/2
library(compiler)
gsk3.c <- cmpfun(gsk3)
jmsigner.c <- cmpfun(jmsigner)
joshua.c <- cmpfun(joshua)
james.c <- cmpfun(james)

microbenchmark(joshua(p),joshua.c(p),gsk3(p),gsk3.c(p),jmsigner(p),james(p),jmsigner.c(p),james.c(p))
           expr      min        lq    median        uq      max
1     gsk3.c(p)  251.782  255.0515  266.8685  269.5205  457.998
2       gsk3(p)  256.262  261.6105  270.7340  281.3560 2940.486
3    james.c(p)   38.418   41.3770   43.3020   45.6160  132.342
4      james(p)   38.934   42.1965   43.5700   47.2085 4524.303
5 jmsigner.c(p) 2047.739 2145.9915 2198.6170 2291.8475 4879.418
6   jmsigner(p) 2047.502 2169.9555 2258.6225 2405.0730 5064.334
7   joshua.c(p)  237.008  244.3570  251.7375  265.2545  376.684
8     joshua(p)  237.545  244.8635  255.1690  271.9910  430.566

comparación compilada

¡Pero espera! Dirk escribió esto de Rcpp. ¿Puede un completo incompetente en C++ leer su documento JSS, adaptar su ejemplo y escribir la función más rápida de todas? Estén atentos, queridos oyentes.

library(inline)
cpp_if_src <- '
  Rcpp::NumericVector xa(a);
  int n_xa = xa.size();
  for(int i=0; i < n_xa; i++) 
    if(xa[i]<0) xa[i] = 0;
  
  return xa;
'
cpp_if <- cxxfunction(signature(a="numeric"), cpp_if_src, plugin="Rcpp")
microbenchmark(joshua(p),joshua.c(p),gsk3(p),gsk3.c(p),jmsigner(p),james(p),jmsigner.c(p),james.c(p), cpp_if(p))
         expr      min        lq    median        uq       max
1   cpp_if(p)    8.233   10.4865   11.6000   12.4090    69.512
2     gsk3(p)  170.572  172.7975  175.0515  182.4035  2515.870
3    james(p)   37.074   39.6955   40.5720   42.1965  2396.758
4 jmsigner(p) 1110.313 1118.9445 1133.4725 1164.2305 65942.680
5   joshua(p)  237.135  240.1655  243.3990  250.3660  2597.429

con comparación rcpp

Eso es afirmativo, capitán.

Esto modifica la entrada. p incluso si no lo asignas. Si quieres evitar ese comportamiento, tienes que clonar:

cpp_ifclone_src <- '
  Rcpp::NumericVector xa(Rcpp::clone(a));
  int n_xa = xa.size();
  for(int i=0; i < n_xa; i++) 
    if(xa[i]<0) xa[i] = 0;
  
  return xa;
'
cpp_ifclone <- cxxfunction(signature(a="numeric"), cpp_ifclone_src, plugin="Rcpp")

Lo que desafortunadamente mata la ventaja de la velocidad.

yo usaría pmax porque ifelse puede ser un poco lento a veces y el reemplazo de subconjuntos crea un vector adicional (que puede ser un problema con grandes conjuntos de datos).

set.seed(21)
pred_precipitation <- rnorm(25,2,4)
p <- pmax(pred_precipitation,0)

Sin embargo, el reemplazo de subconjuntos es, con mucho, el más rápido:

library(rbenchmark)
gsk3 <- function(x)  x[x<0] <- 0; x 
jmsigner <- function(x) ifelse(x<0, 0, x)
joshua <- function(x) pmin(x,0)
benchmark(joshua(p), gsk3(p), jmsigner(p), replications=10000, order="relative")
         test replications elapsed relative user.self sys.self
2     gsk3(p)        10000   0.215 1.000000     0.216    0.000
1   joshua(p)        10000   0.444 2.065116     0.416    0.016
3 jmsigner(p)        10000   0.656 3.051163     0.652    0.000

micropunto de referencia de trazado automático

Alternativamente, también puede usar ifelse:

ifelse(pred_precipitation < 0, 0, pred_precipitation)

Puntuaciones y reseñas

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *