根据事件的发生向 Seaborn Facet Grid 图添加垂直线

Add vertical lines to Seaborn Facet Grid plots based on the occurrence of an event

我有 60 个月内 50 个不同个体的面板数据。我已经使用 Seaborn 创建了分面网格来绘制每个人随时间变化的基调,现在想为事件发生时添加垂直线。理想情况下,我想在事件 1 发生时添加一条蓝线,在事件 2 发生时添加一条红线。

数据样本:

f_a    tone    t     event1    event2
01_01  -1.9    0       0         0
01_01  -1.1    1       1         0
01_01  -2.5    2       0         0
01_01  -3.0    3       0         1
...
01_01   1.3    40      1         0
01_01   0.7    41      0         0
01_01  -0.6    42      0         0
01_01  -2.3    43      0         1
  1. 'f_a'是ID(分组变量)
  2. 'tone'是y轴
  3. 't'是时间变量
  4. 如果事件发生在时间段 t 期间,
  5. 'event1' 和 'event2' 等于 1,否则为零。

这是我必须创建绘图的代码:

# Initialize a grid of plots with an Axes for each pair
grid1 = sns.FacetGrid(df,col='f_a',hue='f_a',col_wrap=5,height=1.5)

#Draw a horizontal line to show the starting point
grid1.map(plt.axhline,y=0,ls=":",c=".5")

#Draw a line plot to show the trajectory of tone for each f-a pair over time
grid1.map(plt.plot,"t","tone",marker='o')

这是绘图输出的示例: Plots

这是我用来生成数据的代码:

# Create list of observation pairs
fs = np.arange(1,11,1)
ans = np.arange(1,6,1)
f_a=[str(f).zfill(2)+'_'+str(a).zfill(2) 
     for f in fs for a in ans]
# Create dataframe with ARMA process by f_a pair with 60 months of observations of tone
# per pair
d={}
for f in f_a:
    arparams = np.array([.5, .25])
    maparams = np.array([.5, .3])
    ar = np.r_[1,-arparams]
    ma = np.r_[1, maparams]
    y = sm.tsa.arma_generate_sample(ar,ma,60)
    d[f]=y
    
df=pd.melt(pd.DataFrame(d)).rename(columns={'variable':'f_a','value':'tone'})
df['t']=df.groupby('f_a').cumcount()

# One occurrence of event 1 and 2 per f_a pair
up = [np.random.choice(np.arange(2,61,1)) for f in f_a]
down = [np.random.choice(np.arange(2,61,1)) for f in f_a]

# Dataframe with event 1 and 2
events=pd.DataFrame(data=[f_a,up,down]).T.rename(columns={0:'f_a',1:'event1_t',2:'event2_t'})

# Merge Datasets
df=df.merge(right=events,how='left',on='f_a')

# Create dummies for event1/event2
df['event1']=(df.t==df.event1_t)*1
df['event2']=(df.t==df.event2_t)*1

# Clean up dataset
df=df.drop(columns=['event1_t','event2_t'])

您可以使用 axvline 遍历您的组并绘制线条。要遍历子图,请使用 grid1.axes:

for ax, (_, subdata) in zip(grid1.axes, df.groupby('f_a')):
    xs = subdata[subdata['event1'] == 1].t
    for x in xs:
        ax.axvline(x, color='r', ls='--')

    xs = subdata[subdata['event2'] == 1].t
    for x in xs:
        ax.axvline(x, color='b', ls='--')