Comment générer des données de séries chronologiques binaires auto-corrélées aléatoires?

15

Comment puis-je générer des séries temporelles binaires telles que:

  1. La probabilité moyenne d'observer 1 est spécifiée (disons 5%);
  2. Probabilité conditionnelle d'observer 1 au temps étant donné la valeur à t - 1 (disons 30% si t - 1tt1t1 valeur était 1)?
user333
la source

Réponses:

17

Utilisez une chaîne de Markov à deux états.

Si les états sont appelés 0 et 1, alors la chaîne peut être représentée par une matrice 2x2 donnant les probabilités de transition entre les états, où P i j est la probabilité de passer de l'état i à l'état jPPijij . Dans cette matrice, chaque ligne doit totaliser 1,0.

D'après l'énoncé 2, nous avons , et la conservation simple dit alors P 10 = 0,7P11=0.3P10=0.7 .

À partir de l'énoncé 1, vous voulez que la probabilité à long terme (également appelée équilibre ou état stationnaire) soit . Cela signifie que P 1 = 0,05 = 0,3 P 1 + P 01 ( 1 - P 1 ) La résolution donne P 01 = 0,0368421 et une matrice de transition P = ( 0,963158 0,0368421 0,7 0,3 )P1=0.05

P1=0.05=0.3P1+P01(1P1)
P01=0.0368421
P=(0.9631580.03684210.70.3)

(Vous pouvez vérifier l'exactitude de votre matrice de transtion en la portant à une puissance élevée - dans ce cas, 14 fait le travail - chaque ligne du résultat donne les probabilités identiques en régime permanent)

Maintenant, dans votre programme de nombres aléatoires, commencez par choisir au hasard l'état 0 ou 1; cela sélectionne la ligne de que vous utilisez. Utilisez ensuite un nombre aléatoire uniforme pour déterminer l'état suivant. Crachez ce nombre, rincez, répétez si nécessaire.P

Mike Anderson
la source
Solution intéressante! Avez-vous peut-être un exemple de code dans R? Antone autre?
user333
@Mike Pouvez-vous s'il vous plaît enregistrer votre compte? Vous êtes un utilisateur très actif et nous devons le fusionner manuellement encore et encore. Le processus est assez simple; visitez simplement stats.stackexchange.com/login
Merci. Comment estimer la chaîne de Markov (matrice de transition) compte tenu des données? Existe-t-il une fonction R pour cela?
user333
6

J'ai pris une fissure au codage de la réponse de @Mike Anderson dans R. Je ne pouvais pas comprendre comment le faire en utilisant sapply, alors j'ai utilisé une boucle. J'ai légèrement changé les probs pour obtenir un résultat plus intéressant, et j'ai utilisé 'A' et 'B' pour représenter les états. Laissez-moi savoir ce que vous pensez.

set.seed(1234)
TransitionMatrix <- data.frame(A=c(0.9,0.7),B=c(0.1,0.3),row.names=c('A','B'))
Series <- c('A',rep(NA,99))
i <- 2
while (i <= length(Series)) {
    Series[i] <- ifelse(TransitionMatrix[Series[i-1],'A']>=runif(1),'A','B')
    i <- i+1
}
Series <- ifelse(Series=='A',1,0)
> Series
  [1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1
 [38] 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
 [75] 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 1

/ edit: En réponse au commentaire de Paul, voici une formulation plus élégante

set.seed(1234)

createSeries <- function(n, TransitionMatrix){
  stopifnot(is.matrix(TransitionMatrix))
  stopifnot(n>0)

  Series <- c(1,rep(NA,n-1))
  random <- runif(n-1)
  for (i in 2:length(Series)){
    Series[i] <- TransitionMatrix[Series[i-1]+1,1] >= random[i-1]
  }

  return(Series)
}

createSeries(100, matrix(c(0.9,0.7,0.1,0.3), ncol=2))

J'ai écrit le code original alors que j'apprenais juste le R, alors coupez-moi un peu. ;-)

Voici comment vous pourriez estimer la matrice de transition, compte tenu de la série:

Series <- createSeries(100000, matrix(c(0.9,0.7,0.1,0.3), ncol=2))
estimateTransMatrix <- function(Series){
  require(quantmod)
  out <- table(Lag(Series), Series)
  return(out/rowSums(out))
}
estimateTransMatrix(Series)

   Series
            0         1
  0 0.1005085 0.8994915
  1 0.2994029 0.7005971

L'ordre est inversé par rapport à ma matrice de transition d'origine, mais il obtient les bonnes probabilités.

Zach
la source
Génial! Je vais dès que pissible ... semble assez bon ....
user333
Est-il possible de faire l'inverse? Étant donné la série, estimer la matrice?
user333
Pr(Xt=i|Xt1=j)
+1, mais j'ai aussi quelques commentaires: une forboucle serait un peu plus propre ici, vous connaissez la durée Series, alors utilisez-la for(i in 2:length(Series)). Cela élimine le besoin de i = i + 1. Aussi, pourquoi d'abord échantillonner A, puis convertir en 0,1? Vous pouvez directement goûter les 0«et 1».
Paul Hiemstra
2
Plus généralement, vous pouvez ensuite l'envelopper dans une nouvelle fonction createAutocorBinSeries = function(n=100,mean=0.5,corr=0) { p01=corr*(1-mean)/mean createSeries(n,matrix(c(1-p01,p01,corr,1-corr),nrow=2,byrow=T)) };createAutocorBinSeries(n=100,mean=0.5,corr=0.9);createAutocorBinSeries(n=100,mean=0.5,corr=0.1);pour permettre une autocorrélation arbitraire et prédéfinie du décalage 1
Tom Wenseleers
1

Voici une réponse basée sur le markovchainpackage qui peut être généralisé à des structures de dépendance plus complexes.

library(markovchain)
library(dplyr)

# define the states
states_excitation = c("steady", "excited")

# transition probability matrix
tpm_excitation = matrix(
  data = c(0.2, 0.8, 0.2, 0.8), 
  byrow = TRUE, 
  nrow = 2,
  dimnames = list(states_excitation, states_excitation)
)

# markovchain object
mc_excitation = new(
  "markovchain",
  states = states_excitation,
  transitionMatrix = tpm_excitation,
  name = "Excitation Transition Model"
)

# simulate
df_excitation = data_frame(
  datetime = seq.POSIXt(as.POSIXct("01-01-2016 00:00:00", 
                                   format = "%d-%m-%Y %H:%M:%S", 
                                   tz = "UTC"), 
                        as.POSIXct("01-01-2016 23:59:00", 
                                   format = "%d-%m-%Y %H:%M:%S", 
                                   tz = "UTC"), by = "min"),
  excitation = rmarkovchain(n = 1440, mc_excitation))

# plot
df_excitation %>% 
  ggplot(aes(x = datetime, y = as.numeric(factor(excitation)))) + 
  geom_step(stat = "identity") + 
  theme_bw() + 
  scale_y_discrete(name = "State", breaks = c(1, 2), 
                   labels = states_excitation)

Cela vous donne:

entrez la description de l'image ici

tchakravarty
la source
0

J'ai perdu la trace du document où cette approche a été décrite, mais voici.

Décomposer la matrice de transition en

T=(1pt)[1001]+pt[p0p0(1p0)(1p0)]=(1pt)I+ptE

1ptptp0 est la probabilité d'équilibre d'être dans le premier état).

ptT11T11=(1pt)+pt(1p0) .

L'une des caractéristiques utiles de cette décomposition est qu'elle se généralise assez facilement à la classe des modèles de Markov corrélés dans les problèmes de dimension supérieure.

Dave
la source
Si quelqu'un a vu le document qui développe cette représentation, faites-le moi savoir.
Dave