Linguagem R - Classificação de dados em intervalos;média;ignorar outliers

StackOverflow https://stackoverflow.com/questions/4843194

  •  27-10-2019
  •  | 
  •  

Pergunta

Estou analisando dados de uma turbina eólica, normalmente é o tipo de coisa que eu faria no excel, mas a quantidade de dados exige algo pesado. Eu nunca usei R antes, então estou apenas procurando algumas dicas.

Os dados consistem em 2 colunas WindSpeed ​​ e Power , até agora eu cheguei a importar os dados de um arquivo CSV e espalhei os dois um em relação ao outro.

O que eu gostaria de fazer a seguir é classificar os dados em intervalos; por exemplo, todos os dados em que WindSpeed ​​ está entre xey e, em seguida, encontre a média da potência gerada para cada intervalo e represente graficamente a curva formada.

A partir dessa média, quero recalcular a média com base nos dados que caem em um dos dois desvios-padrão da média (basicamente ignorando os valores discrepantes).

Quaisquer dicas são apreciadas.

Para aqueles que estão interessados, estou tentando criar um gráfico semelhante a este < / a>. É um tipo de gráfico bastante padrão, mas como eu disse, a quantidade de cisalhamento de dados requer algo mais pesado do que o Excel.

Foi útil?

Solução

Jogue esta versão, semelhante em motivação à de @ hadley, na mistura usando um modelo aditivo com um suavizador adaptativo usando o pacote mgcv:

Dados fictícios primeiro, conforme usados 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 o modelo aditivo usando gam(), usando uma seleção adaptativa de suavidade e suavidade via REML

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

Preveja com nosso modelo e obtenha erros padrão de ajuste, use o último para gerar um intervalo de confiança de aproximadamente 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)

Plote tudo e o ajuste de Loess para comparação

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 fit

Outras dicas

Já que você não está mais no Excel, por que não usar uma metodologia estatística moderna que não exige categorização bruta dos dados e métodos ad hoc para remover valores discrepantes: regressão localmente suave, conforme implementado por loess.

Usando uma pequena modificação nos dados de amostra 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)

Primeiro, criaremos alguns dados de exemplo para tornar o problema concreto:

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

Suponha que queremos agrupar os valores do power entre [0,5), [5,10), etc. Então

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)]))

Agora criamos os valores médios entre os intervalos de interesse.Observe, se você quiser os valores medianos, apenas altere mean para median.Tudo o que resta a fazer é traçá-los:

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

Para obter a média com base em dados que caem dentro de dois desvios padrão da média, precisamos criar uma função um pouco mais complicada:

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)

Eu recomendo também brincar com o ggplot2 do próprio Hadley.Seu site é um ótimo 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")
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top