2012-01-09 11 views
5

Quiero definir una función por partes utilizando R, sin embargo, mi código R falla. Cualquier sugerencia es bienvenida.Cómo definir una función por partes en R

x<-seq(-5, 5, by=0.01) 
    for (x in -5:5){ 
    if (-0.326 < x < 0.652) fx<- 0.632 
    else if (-1.793<x<-1.304) fx<- 0.454 
    else if (1.630<x<2.119) fx<-0.227 
    else fx<- 0 } 
+0

Puede valer la pena aclarar que este ejemplo es una función de paso, una clase especial de funciones por partes. Para las funciones de paso, 'stepfun' (mencionado por @KenWIlliams) y' approxfun' ambos funcionan bien. 'approxfun' también acomoda funciones lineales por partes (pero no funciones por partes generales). – dzeltzer

Respuesta

12

O usted podría utilizar ifelse.

fx <- ifelse(x > -0.326 & x <0.625, 0.632, 
    ifelse(x > -1.793 & x < -1.304, 0.454, 
    ifelse(x > 1.630 & x < 2.119, 0.227, 0))) 
2

Tal vez si divide las condiciones

if((-1.793<x) & (x < 0.652)) ... 

EDIT: Esto no parece ser todo, aquí es un enfoque diferente:

x<-seq(-5, 5, by=0.01) 
fx <- function(x) { 
    res <- rep(0, length(x)) 
    res[(-0.326 < x) & (x < 0.652)] <- 0.632 
    res[(-1.793<x) & (x < (-1.304))] <- 0.454 
    res[(1.630<x) & (x <2.119)] <- 0.227 
    return(res) 
} 
fx(x) 
+0

Gracias por su respuesta. Voy a intentarlo. –

+0

Su enfoque funciona. Muchas gracias. –

+1

Tenga cuidado con esos bits '&'. No es un problema en este caso, pero mejor quedarse con '&&', y también '||' en lugar de '|'. – fotNelton

15

Prueba esto:

x <- seq(-5, 5, 0.01) 
fx <- (x > -0.326 & x <0.625) * 0.632 + 
     (x > -1.793 & x < -1.304) * 0.454 + 
     (x > 1.630 & x < 2.119) * 0.227 
plot(x, fx) 
+0

Agradable.Dada la experiencia de Gabor, apuesto a que esto funciona más rápido (para una gran cantidad de 'segmentos') que mi enfoque de "cambio". –

1

A menos que haya puntos de corte variable, que haría uso de switch. Aquí hay un ejemplo con valores de corte simplificados.

xcuts<-1:10 #the values at which you change fx assignment 
xx<- seq(1.5,10,5, by =10) #vector of fx values to be selected 
switch(max(which(x>xcuts)), 
1= fx<-xx[1], 
2= fx<-xx[2], 
..."et cetera"... 
) 

Loop over x.

+0

muy buen método. Gracias. –

2

Otra opción más, esta vez usando cut.

regions <- c(-Inf, -1.793, -1.304, -0.326, 0.652, 1.63, 2.119, Inf) 
group <- cut(x, regions) 
f_values <- c(0, 0.454, 0, 0.632, 0, 0.227, 0) 
(fx <- f_values[group]) 
+0

gracias. es muy útil –

10

Llego un poco tarde a la fiesta, pero no pude evitar publicar un par de formas más de hacerlo. Ambos aprovechan las capacidades R para trabajar con intervalos en la línea real.

Si define sus puntos de corte y valores de la función en los vectores cuts y vals así:

cuts <- c(-Inf, -1.793, -1.304, -0.326, 0.625, 1.630, 2.119) 
vals <- c( 0, 0.454,  0, 0.632,  0, 0.227,  0) 

continuación, puede utilizar findInterval para buscar de manera eficiente a los valores de x en sus puntos de corte:

fx <- vals[findInterval(x, c(-Inf, cuts))] 

Si esta función necesita hacer algo más elegante que simplemente buscar un valor constante, puede poner expresiones o funciones o lo que quiera en vals, posiblemente usi ng a list si lo desea.

alternativa, ya que esta función es una función escalonada, puede utilizar stepfun:

f <- stepfun(cuts[-1], vals) 
fx <- f(x) 

A continuación, también se llega a utilizar los buenos métodos de trazado de stepfun también.

Cuestiones relacionadas