2011-01-30 18 views
5

Estoy analizando datos de un aerogenerador, normalmente este es el tipo de cosas que haría en Excel, pero la cantidad de datos requiere algo de servicio pesado. Nunca antes había usado R, por lo que estoy buscando algunos indicadores.R Idioma - ordenando datos en rangos; promediando; ignorar valores atípicos

Los datos consisten en 2 columnas velocidad del viento y la potencia , hasta ahora he llegado a la importación de los datos de un archivo CSV y dispersión de los dos trazados uno contra el otro.

Lo que me gustaría hacer a continuación es ordenar los datos en intervalos; por ejemplo, todos los datos donde WindSpeed ​​ están entre xey y luego encuentran el promedio de la potencia generada para cada rango y grafican la curva formada.

A partir de esta media, quiero recalcular el promedio basado en datos que se encuentra dentro de una de dos desviaciones estándar de la media (básicamente ignorando valores atípicos).

Cualquier puntero es apreciado.

Para aquellos que estén interesados, estoy tratando de crear un gráfico similar al this. Es un tipo de gráfico bastante estándar, pero como he dicho, la cantidad de datos de corte requiere algo más pesado que Excel.

Respuesta

2

Throw esta versión, similar en la motivación como @ Hadley, en la mezcla usando un modelo aditivo con un suave adaptativo utilizando el paquete de mgcv:

datos

Maniquí primero, tal como se utiliza por @hadley

w_sp <- sample(seq(0, 100, 0.01), 1000) 
power <- 1/(1+exp(-(w_sp -40)/5)) + rnorm(1000, sd = 0.1) 
df <- data.frame(power = power, w_sp = w_sp) 

ajustar el modelo aditivo usando gam(), utilizando una selección adaptativa más suave y suavidad a través de REML

require(mgcv) 
mod <- gam(power ~ s(w_sp, bs = "ad", k = 20), data = df, method = "REML") 
summary(mod) 

predecir a partir de nuestro modelo y obtener errores estándar de ajuste, utilice éste para generar un intervalo de confianza aproximado del 95%

x_grid <- with(df, data.frame(w_sp = seq(min(w_sp), max(w_sp), length = 100))) 
pred <- predict(mod, x_grid, se.fit = TRUE) 
x_grid <- within(x_grid, fit <- pred$fit) 
x_grid <- within(x_grid, upr <- fit + 2 * pred$se.fit) 
x_grid <- within(x_grid, lwr <- fit - 2 * pred$se.fit) 

Terreno todo y el ajuste loess para la comparación

plot(power ~ w_sp, data = df, col = "grey") 
lines(fit ~ w_sp, data = x_grid, col = "red", lwd = 3) 
## upper and lower confidence intervals ~95% 
lines(upr ~ w_sp, data = x_grid, col = "red", lwd = 2, lty = "dashed") 
lines(lwr ~ w_sp, data = x_grid, col = "red", lwd = 2, lty = "dashed") 
## add loess fit from @hadley's answer 
lines(x_grid$w_sp, predict(loess(power ~ w_sp, data = df), x_grid), col = "blue", 
     lwd = 3) 

adaptive smooth and loess fits

+0

Gracias Gavin esta es una solución mucho mejor. Sin embargo, no puedo hacerlo funcionar (1 Error, 1 Advertencia) – klonq

+0

Error en eval (predvars, data, env): numérico 'envir' arg no de longitud uno – klonq

+0

Causado por la línea pred <- predict (mod, x_grid, se.fit = TRUE) y seguido por el mensaje de advertencia: en predict.gam (mod, x_grid, se.fit = TRUE) : no todos requieren d las variables se han suministrado en newdata! (Estoy usando datos reales, no datos ficticios) – klonq

2

En primer lugar vamos a crear algunos datos de ejemplo para hacer el hormigón problema:

w_sp = sample(seq(0, 100, 0.01), 1000) 
power = 1/(1+exp(-(rnorm(1000, mean=w_sp, sd=5) -40)/5)) 

Supongamos que queremos bin power los valores entre [0,5), [5,10), etc. Entonces

bin_incr = 5 
bins = seq(0, 95, bin_incr) 
y_mean = sapply(bins, function(x) mean(power[w_sp >= x & w_sp < (x+bin_incr)])) 

Hemos creado los valores medios entre los rangos de interés. Tenga en cuenta que si desea los valores medios, simplemente cambie mean a median. Todo lo que queda por hacer, es trazarlos:

plot(w_sp, power) 
points(seq(2.5, 97.5, 5), y_mean, col=3, pch=16) 

Para obtener el promedio basado en datos que caen dentro de dos desviaciones estándar de la media, tenemos que crear una función un poco más complicado:

noOutliers = function(x, power, w_sp, bin_incr) { 
    d = power[w_sp >= x & w_sp < (x + bin_incr)] 
    m_d = mean(d) 
    d_trim = mean(d[d > (m_d - 2*sd(d)) & (d < m_d + 2*sd(d))]) 
    return(mean(d_trim)) 
} 

y_no_outliers = sapply(bins, noOutliers, power, w_sp, bin_incr) 
+0

Podría ser mejor usar 'mad' en lugar de' sd' de manera que los valores atípicos no se inflan también la estimación de la varianza. – hadley

+0

En realidad, simplemente usaría 'median' o' loess' como sugirió en su respuesta. – csgillespie

5

ya que ya no está en Excel, por qué no utilizar una metodología estadística moderna que no requiere de intervalos de crudo de los datos y métodos ad hoc para eliminar valores atípicos: regresión localmente lisa, que se aplica en el loess.

Usando una ligera modificación de datos de ejemplo de csgillespie:

w_sp <- sample(seq(0, 100, 0.01), 1000) 
power <- 1/(1+exp(-(w_sp -40)/5)) + rnorm(1000, sd = 0.1) 

plot(w_sp, power) 

x_grid <- seq(0, 100, length = 100) 
lines(x_grid, predict(loess(power ~ w_sp), x_grid), col = "red", lwd = 3) 
+0

Gracias, he ido con esta solución. Como me ha dado los resultados correctos basados ​​en mi caso de prueba. – klonq

+0

Intenté modelar esto con datos reales y no estoy del todo contento con el resultado. Desafortunadamente no puedo publicar los datos, pero he hecho que el gráfico esté disponible en http://www.myimagespace.com/public/view/full/5617. Aunque es la mejor solución hasta el momento, en realidad no se relaciona estrechamente con los datos. ¿Cómo puedo 'ajustar' el código para obtener una mejor curva de ajuste? – klonq

+0

@klonq Supongo que probablemente no puedas, sin introducir otros problemas. La forma más fácil de conseguir que estos modelos locales se ajusten mejor a los datos es hacerlos más locales (disminuya 'span' en' loess() 'o aumente' k' en 'gam()'. Sin embargo, con bastante frecuencia, la mayor complejidad se ajusta los datos mejoran en algunas áreas, pero las otras en otras. De ahí la suavidad adaptativa que probé en mi ejemplo, donde la suavidad/rugosidad varía en el rango de ajuste, la curva puede ser áspera donde la relación está cambiando y es suave donde hay sin cambios o muy poco. –

0

Me gustaría recomendar también a jugar con propia ggplot2 de Hadley. Su sitio web es un gran recurso: http://had.co.nz/ggplot2/.

# If you haven't already installed ggplot2: 
    install.pacakges("ggplot2", dependencies = T) 

    # Load the ggplot2 package 
    require(ggplot2) 

    # csgillespie's example data 
    w_sp <- sample(seq(0, 100, 0.01), 1000) 
    power <- 1/(1+exp(-(w_sp -40)/5)) + rnorm(1000, sd = 0.1) 

    # Bind the two variables into a data frame, which ggplot prefers 
    wind <- data.frame(w_sp = w_sp, power = power) 

    # Take a look at how the first few rows look, just for fun 
    head(wind) 


    # Create a simple plot 
    ggplot(data = wind, aes(x = w_sp, y = power)) + geom_point() + geom_smooth() 

    # Create a slightly more complicated plot as an example of how to fine tune 
    # plots in ggplot 
    p1 <- ggplot(data = wind, aes(x = w_sp, y = power)) 
    p2 <- p1 + geom_point(colour = "darkblue", size = 1, shape = "dot") 
    p3 <- p2 + geom_smooth(method = "loess", se = TRUE, colour = "purple") 
    p3 + scale_x_continuous(name = "mph") + 
      scale_y_continuous(name = "power") + 
      opts(title = "Wind speed and power") 
Cuestiones relacionadas