R-Sprache – Daten in Bereiche sortieren;Mittelung;Ausreißer ignorieren
Frage
Ich analysiere Daten von einer Windkraftanlage. Normalerweise würde ich so etwas in Excel machen, aber die Datenmenge erfordert etwas Schweres.Ich habe R noch nie zuvor verwendet und suche daher nur nach ein paar Hinweisen.
Die Daten bestehen aus 2 Spalten Windgeschwindigkeit Und Leistung, Bisher bin ich dazu gekommen, die Daten aus einer CSV-Datei zu importieren und die beiden im Streudiagramm gegeneinander darzustellen.
Als Nächstes möchte ich die Daten in Bereiche sortieren.zum Beispiel alle Daten wo Windgeschwindigkeit liegt zwischen x und y und ermitteln Sie dann den Durchschnitt der erzeugten Leistung für jeden Bereich und zeichnen Sie die gebildete Kurve grafisch auf.
Aus diesem Durchschnitt möchte ich den Durchschnitt auf der Grundlage von Daten neu berechnen, die innerhalb einer von zwei Standardabweichungen vom Durchschnitt liegen (Ausreißer werden grundsätzlich ignoriert).
Alle Hinweise sind willkommen.
Für diejenigen, die Interesse haben, versuche ich, ein ähnliches Diagramm zu erstellen Das.Es ist ein ziemlich normaler Diagrammtyp, aber wie gesagt, die große Datenmenge erfordert etwas Schwereres als Excel.
Lösung
Fügen Sie diese Version, deren Motivation der von @hadley ähnelt, hinzu, indem Sie ein additives Modell mit einem adaptiven Smoother-Using-Paket verwenden mgcv
:
Zuerst Dummy-Daten, wie sie von @hadley verwendet werden
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)
Passen Sie das additive Modell an gam()
, unter Verwendung eines adaptiven Glätters und einer Glättungsauswahl über REML
require(mgcv)
mod <- gam(power ~ s(w_sp, bs = "ad", k = 20), data = df, method = "REML")
summary(mod)
Sagen Sie anhand unseres Modells Vorhersagen und erhalten Sie Standardanpassungsfehler. Verwenden Sie letztere, um ein ungefähres 95-%-Konfidenzintervall zu generieren
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)
Plotten Sie alles und vergleichen Sie den Löss
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)
Andere Tipps
Da Sie nicht mehr in Excel arbeiten, können Sie eine moderne statistische Methodik verwenden, die kein grobes Binning der Daten und Ad-hoc-Methoden zum Entfernen von Ausreißern erfordert:Lokal glatte Regression, wie sie von Löss implementiert wird.
Unter Verwendung einer geringfügigen Modifikation der Beispieldaten von 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)
Zunächst erstellen wir einige Beispieldaten, um das Problem zu konkretisieren:
w_sp = sample(seq(0, 100, 0.01), 1000)
power = 1/(1+exp(-(rnorm(1000, mean=w_sp, sd=5) -40)/5))
Angenommen, wir möchten das in den Mülleimer werfen power
Werte zwischen [0,5), [5,10) usw.Dann
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)]))
Wir haben nun die Mittelwerte zwischen den interessierenden Bereichen erstellt.Beachten Sie: Wenn Sie die Medianwerte wünschen, ändern Sie diese einfach mean
Zu median
.Jetzt müssen Sie sie nur noch plotten:
plot(w_sp, power)
points(seq(2.5, 97.5, 5), y_mean, col=3, pch=16)
Um den Durchschnitt auf der Grundlage von Daten zu erhalten, die innerhalb von zwei Standardabweichungen vom Durchschnitt liegen, müssen wir eine etwas kompliziertere Funktion erstellen:
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)
Hier sind einige Beispiele für angepasste Kurven (Weibull-Analyse) für kommerzielle Turbinen:
http://www.inl.gov/wind/software/
Ich würde empfehlen, auch mit Hadleys eigenem ggplot2 herumzuspielen.Seine Website ist eine großartige Ressource: 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")