Linguagem R - Classificação de dados em intervalos;média;ignorar outliers
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.
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)
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)
Aqui estão alguns exemplos de curvas ajustadas (análise de weibull) para turbinas comerciais:
http://www.inl.gov/wind/software/
http://www.irec.cmerp.net/papéis / WOE / papel% 20ID% 20161.pdf
http://www.icaen.uiowa.edu/~ie_155/Lecture / Power_Curve.pdf
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")