Det är kanske inte så ofta man behöver integrera en funktion, dvs
beräkna ytan under en kurva. I statistisk analys är det antagligen
vanligast då man söker en sannolikhet i en kontinuerlig fördelning. I
dylika fall fanns det ‘förr i tiden’ tabeller men nu används enkla
kommandon i något statistikprogram. Koderna nedan visar dock med några
exempel hur detta kan göras med R-kommandon.
För flera av de vanliga fördelningarna - men ej för t.ex.
normalfördelningen - finns det relativt enkla formler för att beräkna
väntevärde och varians, men för andra är man hänvisad till någon
numerisk funktion via dator.
Nedan sker beräkningar både med integrering men också med de vanliga
formlerna och naturligtvis blir resultatet detsamma (för åtminstone ett
antal decimaler). Följande uttryck är generella för alla kontinuerliga
fördelningar:
Väntevärdet (μ), varians (σ-kvadrat)
samt ytan (F(z)) från x = 0 till x =
z (Generellt gäller integreringen från negativ oändlighet och
till z men här diskuteras fördelningar enbart på den positiva
x-axeln):
\[ \begin{align} \large \mu =\int_{}^{} x\cdot f(x)dx & \phantom{litet tomt ut} \large \sigma^{2} = \int_{}^{} (x-\mu)^{2}\cdot f(x) \; dx & \phantom{litet tomt ut} \large F(z) = \int_{0}^{z} f(x) \; dx \end{align} \]
Nedan visas tre fall - en integrering av exponentialfördelningens funktion, en integrering av Weibullfördelningens funktion samt konvertering av en funktion till en sannolikhets- och fördelningsfunktion.
Detta dokument delas in i tre delar:
1. Integrering av exponentialfördelningen
2. Integrering av Weibullfördelningen
3. Skapa och simulera en sannolikhets- och fördelningsfunktion
1. Integrering av exponentialfördelningen
Exemplet nedan visar en vanlig exponentialfördelning vars egenskaper är välkända och uttrycken för väntevärde och varians är enkla:
\[
\begin{align}
\large f(x) = \lambda e^{-\lambda x} & \phantom{litet tomt ut}
\large \mu = \frac{1}{\lambda} & \phantom{litet tomt ut} \large
\sigma^{2} = \frac{1}{\lambda^{2}}
\end{align}
\]
library(ggplot2)
expfunktion <- function(x) {lam*exp(-lam*x)} # Originalfunktionen.
lam = 1.7
grans1 = 0.5
grans2 = 3.1
yta1 <- integrate(expfunktion, grans1, grans2)
yta <- sprintf("%.3f", round(yta1$value, 3))
yta2 <- sprintf("%.3f", round(pexp(grans2, lam) - pexp(grans1, lam), 3))
text1 <- paste0(" Exponentialfördelningen")
text2 <- paste0(" Yta (integration) = ", yta)
text3 <- paste0(" Yta (R-kommandon) = ", yta2)
mingraf <- ggplot() +
xlim(0, 4) +
ylim(0, lam) +
geom_vline(xintercept = c(grans1, grans2)) +
geom_function(fun = expfunktion, colour='blue', linewidth=1.5) +
annotate("text", x=-Inf, y=Inf, label=text1, vjust = 2, hjust=-1, size=4.5, colour="blue") +
annotate("text", x=-Inf, y=Inf, label=text2, vjust = 5, hjust=-1.2, size=4., colour="red") +
annotate("text", x=-Inf, y=Inf, label=text3, vjust = 8, hjust=-1.02, size=4., colour="red") +
xlab('x') + ylab("f(x)")
mingraf
Grafen ovan visar en exponentialfördelning med två gränser och med motsvarande yta. Det är som förväntat samma resultat med bägge beräkningsmetoderna, integrering och R-kommandon.
Beräkning av väntevärde och varians. Beräkningen genomförs både med de generella uttrycket för kontinuerliga fördelningar och formlerna för exponentialfördelningen. Nederst visas resultaten i en tabell:
library(kableExtra)
my <- function(x) {x * expfunktion(x)} # Väntevärde
myinter <- integrate(my, 0, Inf)$value
vari <- function(x){(x-myinter)^2 * expfunktion(x)} # Varians
variinter <- integrate(vari, 0, Inf)$value
myinter <- round(myinter, 3)
variinter <- round(variinter, 3)
medelvarde <- round(1/lam, 3) # Väntevärde o varians i en exp-fördelning.
varians <- round((1/lam)*(1/lam), 3)
a <- c("", "Yta", "Väntevärde", "Varians")
b <- c("Integration", yta, myinter, variinter)
c <- c("R-kommandon", yta2, medelvarde, varians)
df <- data.frame(a, b, c)
names(df) <- NULL
df %>%
kbl(booktabs = T, align = "l") %>%
kable_styling( font_size = 17) %>%
kable_paper(full_width = T) %>%
column_spec(1, bold=TRUE) %>%
column_spec(2, bold=TRUE) %>%
column_spec(3, bold=TRUE)
| Integration | R-kommandon | |
| Yta | 0.422 | 0.422 |
| Väntevärde | 0.588 | 0.588 |
| Varians | 0.346 | 0.346 |
2. Integrering av Weibullfördelningen
Exemplet nedan visar en vanlig Weibullfördelning vars egenskaper är välkända men uttrycken för väntevärde och varians är en smula komplicerade:
\[
\begin{align}
\large \mu = \lambda \cdot \Gamma \left( 1+\frac{1}{k} \right) &
\phantom{litet tomt ut} \large \sigma^{2} = \lambda^{2} \cdot \left(
\Gamma \left( 1+\frac{2}{k} \right) -\Gamma \left(
1+\frac{1}{k}\right)^{2} \right)
\end{align}
\]
library(ggplot2)
Weibfunktion <- function(x) {k/lam * (x/lam)^(k-1) * exp(-(x/lam)^k)} # Originalfunktionen.
k <- 1.5
lam <- 3.7
grans1 <-1.1
grans2 <- 5.3
yta1 <- integrate(Weibfunktion, grans1, grans2)
yta <- sprintf("%.3f", round(yta1$value, 3))
yta2 <- sprintf("%.3f", round(pweibull(grans2, k, lam) - pweibull(grans1, k, lam), 3))
text1 <- paste0(" Weibullfördelningen")
text2 <- paste0(" Yta (integration) = ", yta)
text3 <- paste0(" Yta (R-kommandon) = ", yta2)
mingraf <- ggplot() +
xlim(0, 14) +
geom_vline(xintercept = c(grans1, grans2)) +
geom_function(fun = Weibfunktion, colour='blue', linewidth=1.5) +
annotate("text", x=-Inf, y=Inf, label=text1, vjust = 2, hjust=-1, size=4.5, colour="blue") +
annotate("text", x=-Inf, y=Inf, label=text2, vjust = 5, hjust=-1.2, size=4., colour="red") +
annotate("text", x=-Inf, y=Inf, label=text3, vjust = 8, hjust=-1.02, size=4., colour="red") +
xlab('x') + ylab("f(x)")
mingraf
Grafen ovan visar en Weibullfördelning med två gränser och med motsvarande yta. Det är som förväntat samma resultat med bägge beräkningsmetoderna, integrering och R-kommandon.
Beräkning av väntevärde och varians. Beräkningen genomförs både med de generella uttrycket för kontinuerliga fördelningar och formlerna för Weibullfördelningen. Nederst visas resultaten i en tabell:
library(kableExtra)
my <- function(x) {x * Weibfunktion(x)} # Väntevärde
myinter <- integrate(my, 0, Inf)$value
vari <- function(x){(x-myinter)^2 * Weibfunktion(x)} # Varians
variinter <- integrate(vari, 0, Inf)$value
myinter <- sprintf("%.3f", round(myinter, 3))
variinter <- sprintf("%.3f", round(variinter, 3))
myWeibull <- lam*(gamma(1 + 1/k))
varWeibull <- lam*lam*(gamma(1 + 2/k) - (gamma(1 + 1/k))^2)
myWeibull <- sprintf("%.3f", round(myWeibull, 3)) # Väntevärde o varians i en Weibull-fördelning.
varWeibull <- sprintf("%.3f", round(varWeibull, 3))
a <- c("", "Yta", "Väntevärde", "Varians")
b <- c("Integration", yta, myinter, variinter)
c <- c("R-kommandon", yta2, myWeibull, varWeibull)
df <- data.frame(a, b, c)
names(df) <- NULL
df %>%
kbl(booktabs = T, align = "l") %>%
kable_styling( font_size = 17) %>%
kable_paper(full_width = T) %>%
column_spec(1, bold=TRUE) %>%
column_spec(2, bold=TRUE) %>%
column_spec(3, bold=TRUE)
| Integration | R-kommandon | |
| Yta | 0.670 | 0.670 |
| Väntevärde | 3.340 | 3.340 |
| Varians | 5.143 | 5.143 |
3. Skapa och simulera en sannolikhets- och fördelningsfunktion
Exemplet nedan visar i täljaren en trigonomisk funktion. Ytan under funktionen är 1.455 och såleden divideras funktionen med detta värde för att ytan skall bli 1 och kunna vara en sannolikhetsfördelning (ursprunget till funktionen redovisas inte här):
\[
\begin{align}
\large f(x) = \frac{(sinx)^2 \cdot cosx+0.4} {1.455}
\end{align}
\]
library(ggplot2)
# Antag att följande funktion skall utgöra en sannolikhetsfördelning:
#
# sin(x)^2 * cos(x) + 0.4)
#
# Men ytan under kurvan är inte 1 utan först måste ytan beräknas och
# sedan divideras funktionen med ytan:
f <- function(x) { (sin(x)^2 * cos(x) + 0.4) } # Originalfunktionen.
grans1 = 0
grans2 = 4
area <- integrate(f, grans1, grans2)$value
fordelning <- function(x) {((sin(x)^2 * cos(x) + 0.4))/area} # Sann.fördelning.
mingraf <- ggplot()
mingraf <- mingraf + xlim(grans1, grans2) +xlab('x') + ylab('f(x)')
mingraf <- mingraf + geom_function(fun = fordelning, colour='blue', linewidth=1.5) +
annotate("text", x = 2, y = Inf, label=" En fördelning", vjust = 2, size = 5.5, colour = "blue")
mingraf
Grafen ovan visar fördelningen med två tydliga toppar.
Simulering av data. Data från de vanligaste sannolikhetsgfördelningarna kan simuleras med hjälp av relativt enkla kommandon. Vid ovanligare fördelningar anger litteraturen några olika sätt. Ett av dem kallas ‘The Rejection Method’ (se t.ex. boken SIMULATION av Sheldon M. Ross). Denna metod används nedan genom ett antal rader kod:
# Hitta fördelningens högsta punkt. Skall användas för simulering av
# med den s.k. 'The Rejection Method'.
# Metoden behöver ytterligare en fördelning att användas vid simuleringen.
# Här används en likformig fördelning (g(x)) på intervallet [0, 4] och som
# sålunda har höjden 1/4 (0.25).
# f(x) (sin(x)^2 * cos(x) + 0.4))/area}
# ------ = ---------------------------------- -> c-värdet (sid 66, SIMULATION)
# g(x) 1/4
fxdivgx <- function(x) {0.25*((sin(x)^2 * cos(x) + 0.4))/area} # Sann.fördelning.
maxfxdivgx <- optimize(fxdivgx, interval = c(0, 4), maximum = TRUE)
c <- as.numeric(maxfxdivgx[1])
# f(x)/(c*g(x)) används för att avgöra om ett slumptal skall anses tillhöra
# ovanstående 'fordelning'.
antslump <- 10000
U1 <- runif(antslump, 0, 4)
U2 <- runif(antslump, 0, 4)
z <- fordelning(U1)/(c*0.25)
resultat <- ifelse(U2 < z, U1, NA) # Sid 66-67 i SIMULATION
data <- data.frame(U1, U2, z, resultat)
resultat <- resultat[!is.na(resultat)]
hist <- ggplot() + geom_histogram(aes(resultat, after_stat(density)), bins=20,color='black', alpha = 0.3) +
geom_function(fun = fordelning, colour='blue', linewidth=1.5)
hist
Ovanstående graf visar det simulerade utfallet tillsammans med fördelningen.
Beräkning av väntevärde och varians. Eftersom det inte finns enkla formler för beräkningarna måste den ursprungliga definition används, dvs en integrering av funktionen. Tabellen visar god överensstämmelse mellan teoretiska och simulerade värden:
library(ggplot2)
# beräkna my och varians
totyta <- integrate(fordelning, 0, 4)
myfun <- function(x) {x*fordelning(x)} # my
#myvarde <- round(integrate(myfun, 0, 4)$value, 3)
myvarde <- integrate(myfun, 0, 4)$value
varfun <- function(x){(x-myvarde)^2 * fordelning(x) } # Variance
varians <- round(integrate(varfun, 0, 4)$value, 3)
myvarde <- sprintf("%.3f", round(myvarde, 3))
varians <- sprintf("%.3f", round(varians, 3))
simmedel <- mean(resultat)
simvarians <- var(resultat)
simmedel <- sprintf("%.3f", round(simmedel, 3))
simvarians <- sprintf("%.3f", round(simvarians, 3))
a <- c("", "Väntevärde", "Varians")
b <- c("Integration", myvarde, varians)
c <- c("Simulering", simmedel, simvarians)
df <- data.frame(a, b, c)
names(df) <- NULL
df %>%
kbl(booktabs = T, align = "l") %>%
kable_styling( font_size = 17) %>%
kable_paper(full_width = T) %>%
column_spec(1, bold=TRUE) %>%
column_spec(2, bold=TRUE) %>%
column_spec(3, bold=TRUE)
| Integration | Simulering | |
| Väntevärde | 1.520 | 1.542 |
| Varians | 1.189 | 1.187 |
Skapa fördelningsfunktionen - F(x). Fördelningsfunktionens Y-axel visar hur ‘sannolikhetsytan’ ökar då värdena på X-axeln ökas och funktionen är alltid växande. Ofta anpassar man mätdata till en tänkt fördelningsfunktion för att undersöka överensstämmelse mellan data och model (se t.ex. ‘normalfördelningstest’):
library(ggplot2)
Fx <- c()
Xskala <- c()
for (i in seq(0, 4, by = 0.04)) {
svar <- integrate(fordelning, 0, i)$value
Fx <- append(Fx, svar)
Xskala <- append(Xskala, i)
}
Fxdata <- data.frame(Fx, Xskala)
mingraf <- ggplot() +
xlim(0, 4) +
xlab('x') +
ylab('F(x)') +
geom_point(data=Fxdata, aes(Xskala, Fx), size=1, col="blue") +
geom_path(data=Fxdata, aes(Xskala, Fx), color="blue") +
annotate("text", x = 2, y = Inf, label=" F(x)", vjust = 2, size = 5.5, colour = "blue")
mingraf
Avslutningsvis
Ovanstående koder och texter avser inte att ge
en uttömmande diskussion om integrering av en funktion. Men här har
framställningen poängterat enkelhet.
(Analyserna har gjorts med datorprogrammet ‘R’ och med det grafiska gränssnittet ‘R-studio’ och bägge är gratis tillgängliga på nätet. Se https://www.indstat.se och knappen [Statistikprogram - R] för installation.)
(Se https://www.indstat.se för många andra simuleringsövningar.)