J'ai des données sur 3 types d'événements et je veux estimer les probabilités de transition Pij (1). Ceux-ci indiquent la probabilité qu'un certain événement i soit suivi par l'événement j, étant donné que cet événement est survenu (j'ai donc besoin de probabilités conditionnelles). Je veux aussi savoir Pij (2) et Pij (3), qui est la probabilité conditionnelle que le deuxième (troisième) événement après l'événement i soit l'événement j.Estimer les probabilités de transition (pandas)
Jetez un oeil à certaines données maquette:
import pandas as pd
import numpy as np
np.random.seed(5)
strings=list('ABC')
events=[strings[i] for i in np.random.randint(0,3,20)]
groups=[1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2]
index=pd.date_range('2/2/2012',periods=20,freq='T')
dfm=pd.DataFrame(data={'event':events,'group':groups},index=index)
dfm.head()
event group
2012-02-02 00:00:00 C 1
2012-02-02 00:01:00 B 1
2012-02-02 00:02:00 C 1
2012-02-02 00:03:00 C 1
2012-02-02 00:04:00 A 1
Jusqu'à présent, j'ai suivi une stratégie très inélégante et naïve et utilisé shift
pour voir quels événements se sont produits au cours des prochaines périodes:
#Create new columns containing the shifted values
for i in range(1,4):
dfm['event_t%i'%i]=dfm.event.groupby(dfm.group).shift(-i)
#Combine the columns with current and shifted values into one
for i in range(1,4):
dfm['NEWevent_t%i'%i]=dfm['event']+' '+dfm['event_t%i'%i]
dfm = dfm.drop('event_t%i'%i, 1)
#Count the number of times each combination occurs
A=dfm['NEWevent_t1'].groupby(dfm.group).value_counts()
B=dfm['NEWevent_t2'].groupby(dfm.group).value_counts()
C=dfm['NEWevent_t3'].groupby(dfm.group).value_counts()
merged=pd.concat([A, B, C], axis=1)
Cela donne en effet le nombre de fois qu'une combinaison d'événements spécifique (par exemple AA, AB, ..) se produit pour chaque groupe. Pour ce faire, je peux faire un groupement en utilisant à la fois la variable de groupe et la première lettre de la paire à deux lettres comme variables de regroupement. Cette solution de force brute pourrait ressembler à:
merged=merged.reset_index()
merged['first']=merged['level_1'].apply(lambda x: x[0])
merged.columns=['group','i j','t1','t2','t3','first']
merged.groupby(['group','first'])['t1','t2','t3'].sum()
sums=merged.groupby(['group','first'])['t1','t2','t3'].sum()
merged=pd.merge(merged,sums,left_on=['group','first'],right_index=True)
merged['Pij(1)']=merged.t1_x/merged.t1_y
merged['Pij(2)']=merged.t2_x/merged.t2_y
merged['Pij(3)']=merged.t3_x/merged.t3_y
merged[['group','i j','Pij(1)','Pij(2)','Pij(3)']]
merged.head()
group i j Pij(1) Pij(2) Pij(3)
0 1 A A 0.25 0.666667 0.666667
1 1 A B 0.25 NaN NaN
2 1 A C 0.50 0.333333 0.333333
3 1 B A 0.50 0.500000 0.500000
4 1 B C 0.50 0.500000 0.500000
Je crois qu'il doit y avoir un moyen beaucoup plus facile d'y parvenir? Des suggestions sur la façon de rendre cela plus efficace?
Remarque: mon jeu de données contient 5 millions de lignes, 10 types d'événements et 100 groupes.
Merci. Mais si j'ai raison, il y a un problème avec la ligne 'trans = trans/trans.sum()'. (1) cela semble donner de mauvais résultats et (2) ne peut pas gérer la division par zéro. Une solution serait 'trans = trans.astype (float). Div (trans.sum (axe = 1), axe = 0) trans = trans.fillna (0)'. – Pilik
Merci, je vais y remédier. Cela a fonctionné pour moi, ou je ne l'afficherais pas, mais le vôtre pourrait être plus généralisable. – thefourtheye