Vad är
korskorrelation?
—
Undersökning av en tidsserie
Ingemar Sjöström, SFK-StaM
juni 2025
Bakgrund
Det finns många behov och möjligheter att undersöka en tidsserie och
korskorrelation är ett sätt (CCF — cross correlation function).
De flesta datorprogram har ett stort avsnitt med metoder för
tidsserieanalys. Det är vanligt att beräkna korrelationskoefficienten
mellan två variabler, t.ex. längd och vikt hos samma enhet, t.ex. hos en
människa.
Korskorrelation beräknar i stället korrelationen mellan
mätvärden om den ena tidsserien förskjuts i ‘tidsled’. Kanske man
misstänker att värdena i tidsserie A har en korrelation med tidsserie B
men vi en annan tidpunkt.
Exempel. Antag att vi har delar
av två tidsserier där mätvärdena är från t.ex. olika flöden och inte vid
samma tid. Frågan är då om det finns en korrelation mellan mätvärdena:
Tidsserie A: ____ 49.9 44.1 48.2 54.1 44.9 48.8 47.0 41.8 51.0 49.7
____
Tidsserie B: ____ 2.1 1.4 7.3 4.1 8.9 6.1 7.6 1.1 2.7 6.2 ____
Simulering — tre olika exempel
1. Två helt slumpmässiga serier
2. Två serier där en är en linjär kombination av den andra
3. Två serier där en är en linjär kombination av den andra plus en slumpterm
1. Två helt slumpmässiga serier
Här skapas en tidsserie A med initialt 1000 normalfördelade värden N(50, 4.5) och tidsserie B med 800 normalfördelade värden N(1.5, 0.4). Det finns ingen trend eller inget beroende mellan mätdata. Kodraderna skapar ett diagram (CCF-plott) för att visa korskorrelation mellan de två tidsserierna.
library(ggplot2) # Bibliotek för att rita grafer.
library(forecast) # Bibliotek för att göra graf för ccf.
library(dplyr) #
myA <- 50 # Processens medelvärde (A)
sigmaA <- 4.5 # Processens sigma (A)
antalA <- 1000 # Antal tidsdata (A)
myB <- 1.5 # Processens medelvärde (B)
sigmaB <- 0.4 # Processens sigma (B)
antalB <- 800 # Antal tidsdata (B)
error <- 0.2 # Sigma error
serieA <- rnorm(antalA, myA, sigmaA) # Exempel 1
serieB <- rnorm(antalB, myB, sigmaB)
ggCcf(serieA, serieB, main="Exempel 1 - serie A och Serie B") +
annotate("text", x = 0, y = Inf, label="Ingen error-term, lag 0", vjust=1.5, size=3.5, colour="blue")
Kommentar till simulering 1. Eftersom de simulerade tidsserierna
är helt slumpmässiga förväntas inga konstigheter i diagrammet. Praktiskt
taget alla värden (‘stolpar’) ligger inom
‘felmarginalen’.
CCF-diagrammet skapas av ‘ccf’-kommandot
(cross correlation function) och visar för varje ‘lag’
(tidsförskjutning) korrelationskoefficienten (upp t.o.m. lag +/-30). De
två horisontella streckade linjerna anger att cirka 95 % av alla värden
förväntas ligga inom dessa gränser om det inte finns någon korrelation.
(Eftersom p = 0.05 och n = 60 förväntas 3 värden utanför
gränserna.)
(Notera att CCF-grafen
skapas av ggCdf-kommandot vilket ger ett bättre diagram i denna
mjukvara.)
2. Två serier där en är en linjär kombination av den andra
Här skapas en tidsserie (Serie C) som en funktion av Serie A. Eftersom det inte finns något slumpterm blir korrelationen i CCF-diagrammet exakt 1.0 vid lag 6:
\[
\begin{align}
\Large SerieC = 0.2+0.05 \cdot Serie A \phantom{tomt} (\text{ingen
slumpterm})
\end{align}
\]
serieC <- 0.2 + 0.05*serieA # Exempel 2
serieC <- na.omit(lead(serieC, n = 6)) # Förskjuter data 6 steg.
ggCcf(serieA, serieC, main="Exempel 2 - serie A och Serie C, lag 6") +
annotate("text", x = 0, y = Inf, label="Ingen error-term, lag 6", vjust=1.5, size=3.5, colour="blue")
Kommentar till simulering 2. Vid simuleringen förskjuts Serie C 6 steg (sker med kommandot ‘lead’) och detta plockas lätt upp av analysen som anger korrelationsvärdet 1.0 vid lag 6.
3. Två serier där en är en linjär kombination av den andra plus en slumpterm
Denna simulering är exakt samma som föregående men här med lag 20, samt att data nu innehåller en slumpterm, alltså mer realistisk:
\[
\begin{align}
\Large SerieC = 0.2+0.05 \cdot Serie A + N(0, 0.2)
\phantom{tomt.} (N(0, 0.2) \text{ slumpterm, sigma = 0.2})
\end{align}
\]
serieC <- 0.2 + 0.05*serieA # Exempel 3
serieC <- na.omit(lead(serieC, n = 20))
serieD <- serieC + rnorm(length(serieC), 0, error)
ggCcf(serieA, serieD, main="Exempel 3 - serie A och Serie D, lag 20") +
annotate("text", x = 0, y = Inf, label="Inkl error-term, lag 20", vjust=1.5, size=3.5, colour="blue")
Kommentar till simulering 3. Denna analys plockar fram
korskorrelationen mellan de två serierna och högsta värdet hittas vid
lag 20. Eftersom data nu innehåller en slumpterm blir den beräknade
korrelationen cirka 0.65. Om data innehåller en ännu större slumpterm
(brus) kommer ju ‘korrelationsignalen’ att bli allt lägre.
Men med
kännedom om processens olika flöde går det kanske att hitta en anledning
till en korrelation mellan det två tidsserierna vid lag 20.
Avslutningsvis. Vid analys av data ingår det att klämma och vrida på datamängden för att förstå dess hemligheter. Till detta behöver man ett lämpligt datorprogram och många av dem har har verktyg för tidsserieanalys och om man har datamängden preparerad tar kontrollen ovan bara några sekunder.
(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.)
(Se https://www.ing-stat.se/autokorr.html för simulering av s.k. auto correlation.)