##identify pulses #pad dataset by sampling interval in case there are any missing values sample_interval = xmin df['timestamp'] df.set_index('timestamp', inplace=True) df_padded = df.resample('20min').asfreq() #find 150 rolling mean df['atnrm150']=df['atn'].rolling(150, min_periods=23).mean() #Find raw, 24H rolling mean, 3-d rolling mean, 5-d rolling mean df['rm24h'] = df['val'].rolling('24h').mean() df['rm3d'] = df['val'].rolling('3d').mean() df['rm5d'] = df['val'].rolling('5d').mean() #find mean +2SD threshold for those stats = {} for col in columns_to_calc: mean = df[col].mean() sd = df[col].std() stats[f'{col}_mean_plus_2sd'] = mean + (2 * sd) atnlimit_raw = stats['atn_mean_plus_2sd'] atnlimit_24H = stats['rm24h_mean_plus_2sd'] atnlimit_3d = stats['rm3d_mean_plus_2sd'] atnlimit_5d = stats['rm5d_mean_plus_2sd'] #Value exceeds dataset mean + 2SD for at least 3 of the following datasets: raw values, 24H rolling mean, 3-day rolling mean, and 5-day rolling mean. df['Pulsecheck_atnraw']=np.where(df['atn'] >= atn_mean_plus_2sd, 1, 0) df['Pulsecheck_rm24h']=np.where(df['rm24h'] >= rm24h_mean_plus_2sd, 1, 0) df['Pulsecheck_rm3d']=np.where(df['rm3d'] >= rm3d_mean_plus_2sd, 1, 0) df['Pulsecheck_rm5d']=np.where(df['rm5d'] >= rm5d_mean_plus_2sd, 1, 0) #“Pulse” starts with the first time this condition is met, and ends when the following 24 hours do not meet this condition. df['Pulsecheckcount'] = df[['Pulsecheck_atnraw', 'Pulsecheck_rm24h', 'Pulsecheck_rm3d', 'Pulsecheckrm5d']].sum(axis=1) df['Pulsecheck_count']=np.where(df['Pulsecheckcount'] >= 3, 1, 0) # Returns True if any value in the last 24h was > threshold df['Pulsecheck_24prior'] = df['Pulsecheck_count'].rolling(window='24h').max() >= 1